В интернет-магазине клиента стоимость доставки считается «на лету» для нескольких служб доставки исходя из веса и габаритов заказа. Проблема появилась на заказе с более чем двадцатью товарами, скрипт неправильно вычислил габариты всего заказа что привело к очень сильной ошибке в стоимости доставки для реального клиента.
Варианты решений
Оказалось, что задачи на упаковку — это целый класс математических задач, для большинства из которых до сих пор не найдены универсальные решения. Но наша задача не требует идеального решения — нам достаточно чтобы габариты считались более-менее близко к размерам итоговой упаковки.
Одно из потенциальных решений — делать из товаров «стопку». Т.е. брать товар с самой большой по площади стороной и ставить на него товар со следующей по площади стороной (сами товары упакованы в коробки-параллелепипеды). И этот способ неплохо себя показывает в ситуации, когда товара в заказе две штуки.
Также метод себя неплохо покажет и в том случае, если в заказе все товары «плоские» — когда высота коробок гораздо меньше длины и ширины, а последние одинаковые. Как у коробок с пиццей.
Но в случае, когда в заказе много товаров с небольшой разницей между длиной, шириной и высотой, такой метод дает серьёзный сбой — мы получаем высокую узкую «башню» или «поезд». В курьерских службах доставка такой «башни» из-за слишком большой длины одной стороны будет или очень дорогой или вообще невозможной.
Особенности реализации
Во всех службах доставки есть такое понятие, как «объемный вес» — когда вес посылки незначителен по сравнению с её габаритами (например, доставляем листы пенопласта), в расчёте стоимости доставки будет учитываться не реальный вес посылки, а условный, вычисленный на основе её габаритов. Мы решили сделать подобный механизм для габаритов посылки, состоящей из нескольких товаров, и вычислить условные габариты посылки, на основе которых и будем считать стоимость доставки.
Важное допущение: получившиеся габариты коробки скорее всего будут не совпадать с реальной коробкой, но объем и габариты «условной коробки» должны быть максимально приближены к реальной.
Второе допущение: в расчёт мы первоначально закладываем некие пропорции условной коробки. В нашем случае мы взяли пропорции высоты, ширины и длины как 1 к 2 к 3, т.е. длина равна трём высотам, а ширина — двум.
Первый шаг вычислений — сложить объёмы всех товаров и вычислить габариты «условной коробки» с этим суммарным объёмом и теми пропорциями, которые мы заложили на предыдущем. Мы также добавляем 10% к объему, ибо упаковка никогда не бывает абсолютно плотной.
Вторым шагом определяем максимальные длину, ширину и высоту из всех товаров в заказе. Таким образом получаем те габариты, меньше которых наша условная коробка в принципе быть не может.
На третьем шаге сравниваем габариты условной коробки и максимальные габариты товаров. Увеличиваем сторону коробки, если длина, ширина или высота одного из товара превышает её.
Эффект от проведенных работ
В результате мы получили алгоритм, который гораздо точнее считает габариты итоговой упаковки заказа. Скрипт не позволяет вычислить точную стоимость доставки до того, как заказ упакует кладовщик, но размер ошибки снизился в десятки раз, что позволило в момент заказа показывать клиенту адекватную стоимость доставки.