feat(generator): корзина отвязана от страницы, у товара — уровень спроса

- Зачем:
  - приёмка #40 нашла в торговых данных два точных равенства, каких в живом
    магазине не бывает: событие корзины случалось ровно у визитов со
    страницей /cart, а внутри такого визита в корзину уходили все открытые
    карточки. Привлекательность товара было нечем измерить, а аналитик читал
    бы эти равенства как склейку в разметке.
- Что:
  - класть в корзину может любой визит, открывший карточку; страница /cart
    осталась шагом воронки, а у визита, дошедшего до неё, корзина непуста.
  - у товара появился уровень спроса — колонка каталога с тремя значениями
    и два ряда вероятностей в числах мира: намерение визита берётся из шага
    воронки, а не из метки покупателя, которая уже действует через неё.
  - уровни рассыпаны по каталогу одной колодой: одинакового расклада по
    категориям нет, связи с ценой нет, и то и другое сторожится тестами.
  - числа мира перемерены: конверсия карточки в корзину 8,62% (по уровням
    13,1 / 9,2 / 5,8), кладут без открытия корзины 41,4% таких визитов,
    средний день 49 834 события, конверсия визита в покупку 2,43%.
  - спека генератора и мастер-спека приведены к новой форме каталога.
- Проверка:
  - make lint && make typecheck && make test — 394 passed (было 383).
  - трафиковая половина побайтово та же: sha256 по (URL, времени, WatchID)
    всех просмотров за 14 канонических дней совпадает со снимком до правки.
This commit is contained in:
ddadmin committed 2026-08-02 22:46:30 +03:00
1 parent 4165f10cdd
commit c0f4d21df9
10 files changed
+734 -248

No files matched your search

+3 -2
View File
@@ -258,8 +258,9 @@ def _walk(
goods = catalog.catalog()
shown = page == Page.PRODUCT
row_category = np.repeat(visits.category, visits.pages)[shown]
# Товар — равномерно внутри категории визита: популярность строк не
# моделируется, каталог дорастает механически (см. `catalog`).
# Товар — равномерно внутри категории визита: карточки всех товаров
# открывают одинаково часто, а различает их уровень спроса — уже в
# корзине, а не в показе (см. `catalog`).
inside = rng.integers(0, goods.count[row_category])
product = np.full(total, -1, dtype=np.int64)
product[shown] = goods.grouped[goods.first[row_category] + inside]