コード例 #1
0
 def test_pack_boxes_tight_fit_many(self):
     '''
     tests a tight fit for non-cubic items
     '''
     item = ItemTuple('Item1', [1, 3, 3], 0)
     item_info = [item] * 82
     box_dims = [9, 9, 9]
     packed_items = pack_boxes(box_dims, item_info)
     expected_return = [[item] * 81, [item]]
     self.assertEqual(2, len(packed_items))
     self.assertEqual(expected_return, packed_items)
コード例 #2
0
    def test_pack_boxes_100_items(self):
        '''
        test many items into one box with inexact fit
        '''
        item = ItemTuple('Item1', [5, 5, 5], 0)
        item_info = [item] * 100

        box_dims = [51, 51, 6]
        packed_items = pack_boxes(box_dims, item_info)

        self.assertEqual(len(packed_items), 1)
コード例 #3
0
 def test_pack_boxes_three_item_one_box(self):
     '''
     test odd sized items will be rotated to fit
     '''
     item1 = ItemTuple('Item1', [13, 13, 31], 0)
     item2 = ItemTuple('Item2', [8, 13, 31], 0)
     item3 = ItemTuple('Item3', [5, 13, 31], 0)
     item_info = [item1, item2, item3]
     box_dims = [13, 26, 31]
     packed_items = pack_boxes(box_dims, item_info)
     self.assertEqual(packed_items, ([[item1, item2, item3]]))
コード例 #4
0
 def test_pack_boxes_tight_fit_many_oblong_inexact(self):
     '''
     tests that the algorithm remains at least as accurate as it already is
     if it were perfect, the first box would have 48 in it
     '''
     item = ItemTuple('Item1', [1, 2, 3], 0)
     item_info = [item] * 49
     box_dims = [4, 8, 9]
     packed_items = pack_boxes(box_dims, item_info)
     self.assertEqual(2, len(packed_items))
     self.assertGreaterEqual(44, len(packed_items[0]))
コード例 #5
0
    def test_pack_boxes_dim_over_2(self):
        '''
        test that when length of item <= length of box / 2 it packs along
        longer edge
        '''
        item = ItemTuple('Item1', [3, 4, 5], 0)
        item_info = [item] * 4

        box_dims = [6, 8, 10]

        packed_items = pack_boxes(box_dims, item_info)
        self.assertEqual(packed_items, ([[item, item, item, item]]))
コード例 #6
0
    def test_pack_3_boxes(self):
        '''
        test that multiple parcels will be selected
        '''
        item = ItemTuple('Item1', [4, 4, 12], 0)
        item_info = [item] * 3
        # item_info = [['Item1', [2, 2, 12]]] * 3  # no error
        # item_info = [['Item1', [4, 4, 12]]] * 2  # no error
        box_dims = [4, 4, 12]

        packed_items = pack_boxes(box_dims, item_info)
        self.assertEqual(packed_items, ([[item], [item], [item]]))
コード例 #7
0
    def test_slightly_larger_box(self):
        '''
        test inexact dimensions
        '''
        # Fails due to recursion limits reached
        item = ItemTuple('Item1', [4, 4, 12], 0)
        item_info = [item] * 2
        box_dims = [5, 8, 12]
        # box_dims = [4, 8, 12]  # passes

        packed_items = pack_boxes(box_dims, item_info)
        self.assertEqual(packed_items, ([[item, item]]))
コード例 #8
0
    def test_pack_boxes_odd_sizes(self):
        '''
        test odd sized items will be rotated to fit
        '''
        item1 = ItemTuple('Item1', [3, 8, 10], 0)
        item2 = ItemTuple('Item2', [1, 2, 5], 0)
        item3 = ItemTuple('Item3', [1, 2, 2], 0)
        item_info = [item1, item2, item2, item3]
        box_dims = [10, 20, 20]

        packed_items = pack_boxes(box_dims, item_info)
        self.assertEqual([[item1, item2, item2, item3]], packed_items)
コード例 #9
0
    def test_pack_boxes_100_items_2_boxes(self):
        '''
        test many items separated into 2 boxes with exact fit
        '''
        item = ItemTuple('Item1', [5, 5, 5], 0)
        item_info = [item] * 100

        box_dims = [10, 25, 25]
        packed_items = pack_boxes(box_dims, item_info)

        self.assertEqual(len(packed_items), 2)
        self.assertEqual(len(packed_items[0]), 50)
        self.assertEqual(len(packed_items[1]), 50)
コード例 #10
0
    def test_pack_boxes_odd_sizes_again(self):
        '''
        test items with different dimensions will be rotated to fit into one box
        '''
        item1 = ItemTuple('Item1', [1, 18, 19], 0)
        item2 = ItemTuple('Item2', [17, 18, 18], 0)
        item3 = ItemTuple('Item3', [1, 17, 18], 0)
        item_info = [item1, item2, item3]

        box_dims = [18, 18, 19]

        packed_items = pack_boxes(box_dims, item_info)
        self.assertEqual(packed_items, ([[item1, item2, item3]]))
コード例 #11
0
def compare_pyshipping_with_shotput():
    from random import randint
    from pyshipping import binpack_simple as binpack
    from pyshipping.package import Package
    from time import time
    items = []
    py_items = []
    box_dims = sorted(
        [randint(100, 200),
         randint(100, 200),
         randint(100, 200)])
    num_items = 500
    for _ in xrange(num_items):
        item_dims = sorted(
            [randint(20, 100),
             randint(20, 100),
             randint(20, 100)])
        items.append(ItemTuple(str(volume(item_dims)), item_dims, 0))
        py_items.append(Package((item_dims[0], item_dims[1], item_dims[2]), 0))
    start = time()
    items_packed = pack_boxes(box_dims, items)
    end = time()
    shotput = {
        'num_parcels': len(items_packed),
        'items_per_parcel': [len(parcel) for parcel in items_packed],
        'time': end - start
    }
    py_box = Package((box_dims[0], box_dims[1], box_dims[2]), 0)
    start = time()
    py_items_packed = binpack.packit(py_box, py_items)
    end = time()
    pyshipping = {
        'num_parcels': len(py_items_packed[0]),
        'items_per_parcel': [len(parcel) for parcel in py_items_packed[0]],
        'time': end - start
    }
    if len(items_packed) > len(py_items_packed[0]):
        best_results = 'pyshipping'
    elif len(items_packed) < len(py_items_packed[0]):
        best_results = 'shotput'
    else:
        best_results = 'tie'
    return {
        'shotput': shotput,
        'pyshipping': pyshipping,
        'best_results': best_results
    }
コード例 #12
0
def pre_pack_boxes(box_info, items_info, options):
    '''
    returns the packed items of one specific box based on item_info
    the item info input does not require a db call

    Args
        boxes_info (Dict[
                weight: float
                height: float
                length: float
                width: float
                dimension_units: ('inches', 'centimeters', 'feet', 'meters')
                weight_units: ('grams', 'pounds', 'kilograms', 'onces')
                name: String
            ])
        products_info (List[Dict[
                weight: float
                height: float
                length: float
                width: float
                dimension_units: ('inches', 'centimeters', 'feet', 'meters')
                weight_units: ('grams', 'pounds', 'kilograms', 'onces')
                product_name: String
            ])
        options (Dict[
                max_weight: float
            ])

    Returns
        List[Dict[{
            packed_products: Dict[item, qty],
            total_weight: float
        }]]
    '''
    dimension_units = box_info['dimension_units']
    box_dims = sorted(
        [box_info['width'], box_info['length'], box_info['height']])
    items_to_pack = []
    weight_units = box_info['weight_units']
    box_weight = box_info['weight']
    total_weight = box_weight
    max_weight = options.get('max_weight', 31710)  # given max weight or 70lbs
    for item in items_info:
        dimension_units = item['dimension_units']
        weight_units = item['weight_units']
        sorted_dims = sorted([item['height'], item['length'], item['width']])
        if not does_it_fit(sorted_dims, box_dims):
            raise BoxError('Some of your items are too big for the box you\'ve'
                           ' selected. Please select a bigger box or contact'
                           ' [email protected].')
        item['weight'] = item['weight']
        items_to_pack += [
            ItemTuple(item['product_name'], sorted_dims, int(item['weight']))
        ] * int(item['quantity'])
        total_weight += item['weight'] * int(item['quantity'])
    items_to_pack = sorted(items_to_pack,
                           key=lambda item: item.dimensions[2],
                           reverse=True)
    box_dims = sorted(box_dims)
    items_packed = pack_boxes(box_dims, items_to_pack)
    if math.ceil(float(total_weight) / max_weight) > len(items_packed):
        additional_box = []
        for items in items_packed:
            while weight_of_box_contents(items) + box_weight > max_weight:
                if (weight_of_box_contents(additional_box) + items[-1].weight
                        <= max_weight):
                    additional_box.append(items.pop())
                else:
                    items_packed.append(list(additional_box))
                    additional_box = [items.pop()]
        items_packed.append(additional_box)

    parcel_shipments = []
    for items in items_packed:
        item_qty = Counter()
        parcel_weight = box_weight
        for item in items:
            item_qty[item.item_number] += 1
            parcel_weight += item.weight
        parcel_shipments.append({
            'packed_products': dict(item_qty),
            'total_weight': parcel_weight
        })
    return parcel_shipments