Functional Weave
Code in Python

inventory.pallet-fit@1.0.0

impl/python.py

3,174 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from typing import Optional

from .inventory_pallet_fit_data import PALLETS  ← this capability’s own data, compiled from data/pallets.json into the same file by fune build
from .inventory_pallet_fit_types import Carton, PalletFit, PalletType


def _cartons_per_layer(length: int, width: int, a: int, b: int) -> int:
    """Cartons per layer on a ``length`` x ``width`` deck, base ``a`` x ``b``,
    as the best two-block pattern: one split across the length or the width,
    each block a grid with the carton one way round.
    """
    best = 0
    i = 0
    while i * a <= length:
        best = max(best, i * (width // b) + ((length - i * a) // b) * (width // a))
        i += 1
    j = 0
    while j * b <= width:
        best = max(best, j * (length // a) + ((width - j * b) // a) * (length // b))
        j += 1
    return best


def _positive(name: str, value: int) -> None:
    if isinstance(value, bool) or not isinstance(value, int) or value <= 0:
        raise ValueError("%s must be a whole number greater than zero, received %r" % (name, value))


def pallet_fit(
    carton: Carton, pallet: PalletType, max_load_height_mm: int, max_load_weight_grams: Optional[int], upright: bool
) -> PalletFit:
    """The best stack of identical cartons on a UK or EUR pallet within the limits."""
    _positive("lengthMm", carton.length_mm)
    _positive("widthMm", carton.width_mm)
    _positive("heightMm", carton.height_mm)
    wg = carton.weight_grams
    if isinstance(wg, bool) or not isinstance(wg, int) or wg < 0:
        raise ValueError("weightGrams must be a whole number, not negative, received %r" % (wg,))
    _positive("maxLoadHeightMm", max_load_height_mm)
    mw = max_load_weight_grams
    if mw is not None and (isinstance(mw, bool) or not isinstance(mw, int) or mw < 0):
        raise ValueError("maxLoadWeightGrams must be a whole number, not negative, received %r" % (mw,))
    deck = next((p for p in PALLETS if p.code == pallet), None)
    if deck is None:
        raise ValueError('unknown pallet "%s": expected uk or euro' % (pallet,))

    l, w, h = carton.length_mm, carton.width_mm, carton.height_mm
    choices = [(h, l, w)] if upright else [(h, l, w), (w, l, h), (l, w, h)]
    best: Optional[PalletFit] = None
    for vertical, a, b in choices:
        per_layer = _cartons_per_layer(deck.length_mm, deck.width_mm, a, b)
        layers = max_load_height_mm // vertical
        per_pallet = per_layer * layers
        limited_by = "footprint" if per_layer == 0 else "height"
        if per_layer > 0 and mw is not None and wg > 0:
            by_weight = mw // wg
            if by_weight < per_pallet:
                per_pallet = by_weight
                limited_by = "weight"
        fit = PalletFit(
            pallet_length_mm=deck.length_mm,
            pallet_width_mm=deck.width_mm,
            carton_height_mm=vertical,
            per_layer=per_layer,
            layers=layers,
            per_pallet=per_pallet,
            limited_by=limited_by,
            load_height_mm=0 if per_layer == 0 else -(-per_pallet // per_layer) * vertical,
            load_weight_grams=per_pallet * wg,
        )
        if best is None or fit.per_pallet > best.per_pallet:
            best = fit
    assert best is not None
    return best