sequenceDiagram
autonumber
participant Scenario as Сценарий Выброса Продуктов
participant D as DecayEvaluator
participant Math as Математический Движок
%% ВХОД МЕТОДА
Scenario->>D: Вызов calculateStochasticDecay(raw_products, current_tick)
activate D
Note over D: Вход метода: Список продуктов из холодильника бэкенда и номер текущего такта
loop Построчный проход по каждому продукту в массиве
D->>D: Вычисление времени удержания: delta_t = current_tick - added_at_tick
%% МАТЕМАТИЧЕСКИЙ РАСЧЕТ СТОХАСТИЧЕСКОГО ШАНСА
D->>Math: Расчет шанса отказа пользователя от продукта
activate Math
Math-->>D: Возврат: Вероятность бытового выброса P_waste
deactivate Math
Note over D: Бросок кубика: random_float = Math.random()
alt Ситуация: random_float <= P_waste
Note over D: Пользователю разонравился продукт.<br/>Добавление fridge_item_id в список мусора
end
end
Note over D: Выход метода: Список уникальных UUID отказной еды
D-->>Scenario: Возврат: List<UUID> (Список на удаление)
deactivate D
calculate_stochastic_decay()
Домен: SIMULATION | Контур: Стохастическое бытовое списание продуктов в мусор
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
1. Бизнес-спецификация метода
- Идентификатор метода:
BPDS-SIM-M012 - Системное имя:
calculate_stochastic_decay(raw_products: List<RawProductDto>, current_tick: Long): List<UUID> - Микросервис:
simulation-core-engine - Домен:
SIMULATION - Класс / Компонент:
simulation.engine.helpers.DecayEvaluator
1.1. Описание логики работы
Этот метод выполняет роль бытового аудита холодильника, когда на Шаге 9 выпал сценарий Выброса продуктов (SCENARIO_WASTE_DISPOSAL). Поскольку у Твина в голове нет абстрактного параметра порчи (\(x_2\)), сам сценарий запускается как чисто стохастическое бытовое событие — хаотичное решение пользователя избавиться от еды.
Причина выброса продуктов полностью стохастическая: пользователю банально не понравился вкус, изменились планы на ужин, или продукт слишком долго мозолит глаза в холодильнике и надоел.
Чтобы сымитировать это хаотичное поведение, метод рассчитывает «время удержания» каждого товара в часах (тактах). Чем дольше продукт лежит нетронутым, тем выше стохастическая вероятность того, что пользователь от него откажется. Метод проверяет каждый продукт случайным кубиком, собирает UUID отказных товаров и передает их списком на удаление из базы бэкенда.
1.2. Пошаговое выполнение
- Прием состава холодильника: Метод получает на вход актуальный список продуктов пользователя, извлеченный из приложения.
- Расчет времени нахождения: Для каждого продукта вычисляется дельта времени: текущий такт симуляции минус номер такта, когда продукт был куплен (
added_at_tick). - Определение стохастического шанса отката: На основе категории продукта (
category_id) из памяти извлекается базовый часовой коэффициент отказа \(\lambda_{base}\) (например, для фруктов он выше, так как они надоедают и теряют товарный вид быстрее, чем бакалея). - Калькуляция вероятности списания: Рассчитывается динамический шанс того, что продукт будет выброшен, по формуле: \(P_{waste} = 1 - e^{-\lambda_{base} \cdot \Delta t}\).
- Бросок кубика Бернулли: Генератор случайных чисел выдает случайную дробь от 0.0 до 1.0. Если это число меньше или равно вычисленной вероятности — продукт признается отказным, и его
fridge_item_idзаносится в список на утилизацию.
2. Диаграмма последовательности метода (Вход и Выход флоу)
Диаграмма визуализирует стохастический проход калькулятора по массиву продуктов, где каждый товар проверяется случайным кубиком на предмет бытового отказа пользователя от еды.
3. Схемы данных и SQL-взаимодействие
Этот метод обрабатывает извлеченный массив объектов внутри оперативной памяти симулятора и напрямую запросы к PostgreSQL на этом шаге не отправляет. Все UUID продуктов уже находятся в памяти воркера.
4. Спецификация обмена данными (Вход / Выход)
Данные передаются внутри памяти микросервиса между контуром сценария списания и аналитическим модулем.
4.1. Входной массив продуктов из холодильника бэкенда (Входные параметры)
{
"current_simulation_tick": 105,
"raw_products_fridge": [
{
"fridge_item_id": "8fa1b432-8411-4c12-a111-9992345bcbc1",
"category_id": "FRUITS",
"sku": "BANANA_ECUADOR_KG",
"added_at_tick": 57
}
]
}4.2. Выходной список UUID отказного товара (Выходные параметры для Метода 15)
{
"identified_spoiled_items": [
"8fa1b432-8411-4c12-a111-9992345bcbc1"
],
"stochastic_metadata": {
"product_retention_hours": 48,
"calculated_p_waste": 0.8534
}
}5. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: BACKEND
Заголовок: Реализация калькулятора стохастического бытового списания товаров calculate_stochastic_decay
5.1. Что нужно сделать
- Создать Java-класс
DecayEvaluatorв пакетеsimulation.engine.helpersи пометить его аннотацией@Component. - Зашить базовую матрицу интенсивностей бытового отказа от категорий Алматы во внутреннюю неизменяемую карту
Map<String, Double> decayRates(FRUITS->0.0400,READY_MEALS->0.0300,DAIRY->0.0150,GROCERIES->0.0001). - Написать метод
calculateStochasticDecay, принимающий список DTO продуктов и номер текущего такта. - Внутри цикла по продуктам вычислять время нахождения товара в холодильнике:
long deltaT = currentTick - product.getAddedAtTick(). Добавить проверочный фильтрif (deltaT <= 0) continue;для предотвращения сетевых рассинхронов. - Рассчитывать стохастическую вероятность бытового выброса через функцию
1.0000 - Math.exp(-lambdaBase * (double) deltaT). - Бросать стохастический кубик Бернулли через
ThreadLocalRandom.current().nextDouble(). Если выпавшее число меньше или равно вероятностиpWaste, добавлятьproduct.getFridgeItemId()в результирующий списокList<UUID>.
6. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: МИГРАЦИЯ
Заголовок: Создание индекса idx_fridge_products_added_at в базе данных бэкенда для оптимизации выгрузки возраста продуктов
6.1. Что нужно сделать
Поскольку симулятор в сценарии выброса постоянно анализирует поле даты добавления продуктов added_at для расчета времени нахождения еды в холодильнике (\(\Delta t\)), прикладные эндпоинты бэкенда будут совершать колоссальное количество запросов к этой колонке. Чтобы снизить нагрузку на дисковую подсистему PostgreSQL бэкенда розничной сети Алматы при массовых тактах, необходимо накат B-Tree индекса на стороне бэкенда.
-- Изменения для базы данных бэкенда розничной сети (схема public)
CREATE INDEX IF NOT EXISTS idx_fridge_products_added_at_calc
ON public.fridge_products (added_at);