sequenceDiagram
autonumber
participant Ticker as Метод 1 (SimulationTicker)
participant Disp as ActivationDispatcher
participant DB as База Данных Симулятора
participant RAM as RAM Реестр (TickRegistry)
participant Core as Метод 3 (CoreSimulationEngine)
%% ВХОД МЕТОДА И ВЫЧИТКА ПОПУЛЯЦИИ
Ticker->>Disp: Вызов processActivation(AlmatyTimeContext)
activate Disp
Note over Disp: Вход метода: Текущий такт, час и день недели Алматы
Disp->>DB: SELECT twin_id, chronotype, spontaneity_rate FROM twin_profiles
activate DB
DB-->>Disp: Возврат: Список всех пользователей популяции (20k строк)
deactivate DB
Note over Disp: Инициализация пула виртуальных потоков Java 21+<br/>Каждый пользователь обрабатывается в своем потоке параллельно
%% ВНУТРЕННИЙ СТОХАСТИЧЕСКИЙ ФИЛЬТР
loop Параллельно для каждого пользователя
Disp->>RAM: Запрос уровня голода hunger_x0 (volatile)
activate RAM
RAM-->>Disp: Возврат: Текущий голод (Пример: 0.4500)
deactivate RAM
Note over Disp: Расчет вероятности P_active на основе характера и времени Алматы
Note over Disp: Бросок кубика Бернулли: random_float = Math.random()
alt Ситуация 1: random_float <= P_active (Пользователь АКТИВЕН)
Note over Disp: Выход метода: Генерация X-Request-ID для сессии твина
%% ПЕРЕДАЧА УПРАВЛЕНИЯ СЛЕДУЮЩЕМУ МЕТОДУ
Disp->>Core: Вызов evaluate_next_step(twin_id, tick, requestId)
activate Core
Note over Core: Управление передано в Метод 3 (Инициация транзакции шага)
deactivate Core
else Ситуация 2: random_float > P_active (Пользователь ПАССИВЕН)
Note over Disp: Поток пользователя изолированно завершает работу
end
end
deactivate Disp
Метод 2: calculate_activation_probability()
Домен: SIMULATION | Контур: Стохастическая активация и диспетчеризация
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
1. Бизнес-спецификация метода
- Идентификатор метода:
BPDS-SIM-M02 - Системное имя:
calculate_activation_probability() - Микросервис:
simulation-core-engine - Домен:
SIMULATION - Класс / Компонент:
simulation.engine.scheduler.ActivationDispatcher
1.1. Описание логики работы
Этот метод работает внутри Диспетчера. Он решает, совершит ли конкретный пользователь какое-либо действие в текущем виртуальном часе симуляции. Симулятор не перебирает пользователей вглухую, а использует стохастический фильтр:
- Сначала метод моментально проверяет оперативную память (RAM) — если пользователь критически голоден, он признается активным автоматически. Физиологическая потребность перебивает социальные привычки.
- Если голод не критичен, симулятор оценивает его характер и привычки: сопоставляет хронотип из базы данных с текущим часом суток Алматы (например, любители вечерних закупок в пятницу) и умножает на его личную спонтанность.
- На выходе получается итоговый шанс активности. Симулятор бросает виртуальный кубик (случайное число), и если оно укладывается в этот шанс, пользователь «просыпается» для совершения шага.
1.2. Пошаговое выполнение
- Запрос голода: Метод запрашивает из оперативной памяти (
ConcurrentHashMap) текущий показатель голода пользователя. - Физиологический перехват: Если голод равен или выше
0.9000(критическая стадия), метод сразу возвращает вероятность1.0000, минуя проверку характера. - Оценка привычек: Если голод в норме, метод берет хронотип и спонтанность пользователя из базы данных и рассчитывает социальный шанс активности с учетом часа и дня.
- Свертка Бернулли: Итоговая вероятность берется как максимальное значение между текущим голодом и рассчитанным социальным шансом.
- Бросок кубика: Генерируется случайное число от 0.0 до 1.0. Если число меньше или равно итоговой вероятности — управление передается следующему методу (
evaluate_next_step) для запуска транзакции.
2. Диаграмма последовательности метода (Вход и Выход флоу)
Диаграмма наглядно показывает, как Диспетчер принимает временной контекст от Часов (Метод 1), параллельно вычитывает профили из базы данных, сверяет оперативную память и передает управление Методу 3.
3. Схемы данных и SQL-взаимодействие
Этот метод считывает статические черты характера и расписание активности пользователей из базы данных симулятора.
3.1. Структура таблицы профилей
CREATE TABLE simulation.twin_profiles (
twin_id UUID PRIMARY KEY,
chronotype VARCHAR(32) NOT NULL, -- Временное окно ("FRIDAY_EVENING", "DAILY_LUNCH")
laziness_coefficient NUMERIC(5, 4) NOT NULL, -- Коэффициент лени (будет нужен на шаге 7)
spontaneity_rate NUMERIC(5, 4) NOT NULL, -- Спонтанность (влияет на импульсивные действия)
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);3.2. Чтение популяции планировщиком (Запрос на получение данных)
На каждом часовом такте симулятор выгружает параметры для фильтрации:
SELECT twin_id, chronotype, spontaneity_rate FROM simulation.twin_profiles;4. Спецификация обмена данными (Вход / Выход)
Поскольку метод выполняется параллельно внутри оперативной памяти сервера на виртуальных потоках воркеров, у него нет внешних сетевых HTTP-эндпоинтов. Контракты специфицируются в виде структур данных в памяти.
4.1. Структура входящего контекста времени (Входные параметры от Метода 1)
{
"global_tick": 105,
"hour_of_day": 19,
"day_of_week": "FRIDAY"
}4.2. Структура выходного сигнала запуска (Входные параметры для Метода 3)
Передается только для тех пользователей, которые успешно прошли проверку «кубика» активности.
{
"active_twin_id": "d3b07384-d113-4956-bf8a-e421cd7bf777",
"current_tick": 105,
"x_request_id": "req-t105-active-d3b07384"
}5. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: BACKEND
Заголовок: Реализация Диспетчера стохастической активации пользователей calculate_activation_probability на виртуальных потоках
5.1. Что нужно сделать
- Написать Java-класс
ActivationDispatcherв пакетеsimulation.engine.scheduler. - Подключить вызов метода к получению данных от
SimulationTicker(Метод 1). - При наступлении такта выгружать список всех пользователей через репозиторий
TwinProfileRepository. - Использовать пул виртуальных потоков Java 21+ (
Executors.newVirtualThreadPerTaskExecutor()), чтобы каждый пользователь обрабатывался параллельно и не блокировал общие потоки процессора. - Внутри потока запрашивать голод из
TickRegistry, рассчитывать вероятность по формулеMath.max(hungerX0, Math.min(1.0, 0.05 * modifier * spontaneity))и бросать случайное числоMath.random(). - Для прошедших фильтр пользователей генерировать уникальную строку
X-Request-IDи вызывать метод ЯдраcoreEngine.evaluateNextStep().
6. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: МИГРАЦИЯ
Заголовок: Индексация таблицы twin_profiles для ускорения массовой выгрузки Диспетчером
6.1. Что нужно сделать
- Создать SQL-скрипт миграции СУБД для создания покрывающего индекса B-Tree.
- Индекс должен включать поля
twin_id,chronotypeиspontaneity_rate, чтобы база данных Postgres могла мгновенно отдавать эти данные планировщику без построчного сканирования всего диска.
CREATE INDEX IF NOT EXISTS idx_twin_profiles_scheduler_cover
ON simulation.twin_profiles (twin_id, chronotype, spontaneity_rate);