3v4l.org

run code in 300+ PHP versions simultaneously
<?php declare(strict_types=1); class CanStorageCalculator { public function __construct( public int $maxLayers, public int $cansPerLayer, public int|float $canHeight, public int|float $maxPalletHeight, public int|float $palletBaseHeight, public int|float $tierSheetHeight, public int|float $topFrameHeight ) { } /** * Calculate the storage requirements for the given number of cans and artworks */ public function calculateStorageRequirements(int $totalCans, array $artworks): array { // Calculate the total number of layers required and round the number up to the nearest whole number $totalLayers = ceil($totalCans / $this->cansPerLayer); // Calculate the max number of layers that can fit on a pallet, considering the following: // the max pallet height, can height, tier sheet height, base and top frames height $maxLayersPerPallet = $this->getMaxLayersPerPallet(); // Calculate the number of pallets required and round the number up to the nearest whole number $palletCount = ceil($totalLayers / $maxLayersPerPallet); // Distribute the layers evenly across the pallets $layersPerPallet = $this->distributeLayersEvenly($totalLayers, $palletCount, $maxLayersPerPallet); // Calculate the total number of layers per artwork $numberOfLayersPerArtwork = (new DunnageCalculator())->numberOfLayersPerArtwork($artworks, $this->cansPerLayer); // Get the artworks distribution on each pallet $palletDetails = $this->getPalletDetails($layersPerPallet, $artworks, $numberOfLayersPerArtwork); // Return the pallet count, layers per pallet and total tier sheets required return [ 'palletCount' => $palletCount, 'layersPerPallet' => $layersPerPallet, 'totalTierSheets' => $palletCount + array_sum($layersPerPallet), ]; } /** * Calculate the max number of layers that can fit on a pallet */ private function getMaxLayersPerPallet(): int|float { // Calculate the max layer height based on the can height and tier sheet height $maxLayerHeight = $this->canHeight + $this->tierSheetHeight; // Calculate the total pallet height based on the max pallet height, pallet base height and top frame height $totalPalletHeight = $this->maxPalletHeight - $this->palletBaseHeight - $this->topFrameHeight; // Calculate the max number of layers that can fit on a pallet based on the total pallet height $maxLayersBasedOnHeight = floor($totalPalletHeight / $maxLayerHeight); // Return the min of the max layers based on height and the max layers return min($maxLayersBasedOnHeight, $this->maxLayers); } /** * Distribute the layers evenly across the pallets */ private function distributeLayersEvenly(int|float $totalLayers, int $palletCount, int|float $maxLayersPerPallet): array { $layersPerPallet = []; $remainingLayers = $totalLayers; // Check if the total layers can be evenly distributed across the pallets $evenDistribution = ($totalLayers % $palletCount === 0); if (! $evenDistribution) { // Calculate the ideal layers per pallet $idealLayersPerPallet = floor($totalLayers / $palletCount); // Calculate the remainder of the total layers divided by the pallet count $remainder = $totalLayers % $palletCount; // Distribute the layers across the pallets for ($i = 0; $i < $remainder; $i++) { $layersPerPallet[] = $idealLayersPerPallet + 1; } // Distribute the remaining layers across the pallets for ($i = $remainder; $i < $palletCount; $i++) { $layersPerPallet[] = $idealLayersPerPallet; } } else { // Distribute the layers evenly across the pallets $layersPerPallet = array_fill(0, $palletCount, $totalLayers / $palletCount); } // Return the layers per pallet return $layersPerPallet; } public function getPalletDetails(array $layersPerPallet, array $artworks, array $numberOfLayersPerArtwork): array { $palletDetails = []; $remainingLayers = $numberOfLayersPerArtwork; $palletIndex = 0; foreach ($layersPerPallet as $layers) { $palletDetails[$palletIndex] = []; foreach ($artworks as $artwork => $quantity) { if ($remainingLayers[$artwork] > 0) { $layersForArtwork = min($remainingLayers[$artwork], $layers); $palletDetails[$palletIndex][$artwork] = $layersForArtwork; $remainingLayers[$artwork] -= $layersForArtwork; $layers -= $layersForArtwork; } if ($layers === 0) { break; } } // Remove artworks with zero layers from the pallet details $palletDetails[$palletIndex] = array_filter($palletDetails[$palletIndex], function ($layerCount) { return $layerCount > 0; }); $palletIndex++; } return $palletDetails; } private function getTotalHeight(int $layers): int|float { $totalHeight = $this->palletBaseHeight; $totalHeight += ($layers * ($this->canHeight + $this->tierSheetHeight)); $totalHeight += $this->topFrameHeight; return $totalHeight; } } class DunnageCalculator { private $artworks = []; private $canSize; private $combineSkus = false; private $maxPalletHeight; /** * Set the array of artwork items */ public function artworks(ArtworkItem ...$artworks): self { foreach ($artworks as $artwork) { $this->artworks[$artwork->name] = $artwork->quantity; } return $this; } /** * Set the can size */ public function canSize(string $canSize): self { $this->canSize = $canSize; return $this; } /** * Combine SKUs */ public function combineSkus(bool $combineSkus): self { $this->combineSkus = $combineSkus; return $this; } /** * Set the maximum pallet height */ public function maxPalletHeight(int $maxPalletHeight): self { $this->maxPalletHeight = $maxPalletHeight; return $this; } /** * Calculate dunnage according to the given parameters */ public function calculate(): array { // Get the can size $canSizeConfig = $this->getCanSizeConfig($this->canSize); // Get the pallet item sizes $getPalletItemSizes = $this->getPalletItemSizes(); // Create a new instance of the CanStorageCalculator $canStorageCalculator = new CanStorageCalculator( $canSizeConfig['maxLayers'], $canSizeConfig['cansPerLayer'], $canSizeConfig['canHeight'], $this->maxPalletHeight, $getPalletItemSizes['palletBaseHeight'], $getPalletItemSizes['tierSheetHeight'], $getPalletItemSizes['topFrameHeight'], ); // Combine SKUs // We only combine SKUs if we have more than one artwork if ($this->combineSkus && count($this->artworks) > 1) { // Calculate the total number of cans of all artworks $totalCans = array_sum($this->artworks); // Calculate the number of pallets, layers per pallet and total tier sheets required $requirements = $canStorageCalculator->calculateStorageRequirements($totalCans, $this->artworks); // Calculate the number of layers per artwork $numberOfLayersPerArtwork = $this->numberOfLayersPerArtwork($this->artworks, $canSizeConfig['cansPerLayer']); // Get the distribution of artworks on each pallet $palletDetails = $canStorageCalculator->getPalletDetails($requirements['layersPerPallet'], $this->artworks, $numberOfLayersPerArtwork); return [ 'palletCount' => $requirements['palletCount'], 'layersPerPallet' => $requirements['layersPerPallet'], 'totalTierSheets' => $requirements['totalTierSheets'], 'palletDetails' => $palletDetails, ]; } $result = []; // Not combining SKUs // Iterate through each artwork foreach ($this->artworks as $artwork => $quantity) { // Calculate the number of pallets, layers per pallet and total tier sheets required $requirements = $canStorageCalculator->calculateStorageRequirements($quantity, [$artwork => $quantity]); // Add the artwork to the result array $result[$artwork] = [ 'palletCount' => $requirements['palletCount'], 'layersPerPallet' => $requirements['layersPerPallet'], 'totalTierSheets' => $requirements['totalTierSheets'], ]; } return ['artworks' => $result]; } /** * Calculate the number of layers per artwork * To perform this calculation, we need consider the number of cans per layer */ public function numberOfLayersPerArtwork(array $artworks, int $cansPerLayer): array { $layersPerArtwork = []; // Iterate through the artworks foreach ($artworks as $artwork => $quantity) { // Calculate the number of layers required and round the number up to the nearest whole number $layersPerArtwork[$artwork] = ceil($quantity / $cansPerLayer); } return $layersPerArtwork; } /** * Get the can size configuration */ private function getCanSizeConfig(string $canSize): array { return match ($canSize) { '8.4_oz_sleek' => [ 'maxLayers' => 22, 'cansPerLayer' => 506, 'canHeight' => 4.35, ], '10_oz_sleek' => [ 'maxLayers' => 19, 'cansPerLayer' => 506, 'canHeight' => 5.28, ], '12_oz_sleek' => [ 'maxLayers' => 16, 'cansPerLayer' => 506, 'canHeight' => 6.28, ], '12_oz' => [ 'maxLayers' => 20, 'cansPerLayer' => 389, 'canHeight' => 4.84, ], '16_oz' => [ 'maxLayers' => 16, 'cansPerLayer' => 389, 'canHeight' => 6.28, ], '19.2_oz' => [ 'maxLayers' => 13, 'cansPerLayer' => 389, 'canHeight' => 7.432, ], }; } /** * Get the pallet item sizes * Here you can have different pallets with different sizes */ private function getPalletItemSizes(string $type = 'default'): array { return match ($type) { default => [ 'palletBaseHeight' => 4.5, 'tierSheetHeight' => 0.026, 'topFrameHeight' => 1.0, ] }; } } class ArtworkItem { public string $name; public int $quantity; /** * Set the name of the artwork item */ public function name(string $name): self { $this->name = $name; return $this; } /** * Set the quantity of the artwork item */ public function quantity(int $quantity): self { $this->quantity = $quantity; return $this; } } $calculator = new DunnageCalculator(); $result = $calculator ->artworks( (new ArtworkItem())->name('artwork_1')->quantity(778), (new ArtworkItem())->name('artwork_2')->quantity(5_835), (new ArtworkItem())->name('artwork_3')->quantity(389), ) ->canSize('16_oz') ->combineSkus(true) ->maxPalletHeight(88) ->calculate(); print_r($result);
Output for 8.1.0 - 8.1.28, 8.2.0 - 8.2.19, 8.3.0 - 8.3.7
Fatal error: Uncaught TypeError: CanStorageCalculator::distributeLayersEvenly(): Argument #2 ($palletCount) must be of type int, float given, called in /in/uKPDq on line 34 and defined in /in/uKPDq:71 Stack trace: #0 /in/uKPDq(34): CanStorageCalculator->distributeLayersEvenly(18.0, 2.0, 13.0) #1 /in/uKPDq(228): CanStorageCalculator->calculateStorageRequirements(7002, Array) #2 /in/uKPDq(373): DunnageCalculator->calculate() #3 {main} thrown in /in/uKPDq on line 71
Process exited with code 255.

preferences:
47.91 ms | 402 KiB | 62 Q