- Зачем:
- клиентская сторона мира становится целой: без add_to_cart и purchase
в данных нет ни таксономии событий, ни вложенного JSON, ни денег,
а метка «покупатель» из плана состава ни на что не влияла (#40).
- Что:
- добавлен модуль commerce: корзина шире заказа, номер заказа вида
ГГГГММДД-NNNN, промокод без скидки в сумме, сырой ecommerce через orjson;
- метка покупателя получила два рычага — долгую жизнь куки в плане и
свою воронку в дне; CART_PERCENT опущен с 8 до 6, чтобы конверсия
мира осталась около 2%;
- часть цен каталога получила копейки: productPrice округляется форматом,
purchaseRevenue несёт точную сумму — расхождение живёт внутри события;
- граница суток забирает страницу подтверждения вместе с её покупкой:
потерь на клиентской стороне этот этап не заводит;
- решения и перемеренные числа мира записаны в спеку генератора, §9.
- Проверка:
- make lint && make typecheck && make test — 383 passed (было 353).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
42 lines
1.7 KiB
Python
42 lines
1.7 KiB
Python
"""Идентификаторы событий: неповторяющиеся и переживающие JSON.
|
|
|
|
Обещание одно, но держит его дедупликация при переигровке дня: два
|
|
одинаковых `WatchID` склеили бы разные события (спека, раздел 4).
|
|
"""
|
|
|
|
import numpy as np
|
|
|
|
from clickstream_generator import ids
|
|
from clickstream_generator.seeds import CANONICAL_SEED
|
|
|
|
|
|
def stream(offset: int = 0) -> np.random.Generator:
|
|
return np.random.Generator(np.random.PCG64(CANONICAL_SEED + offset))
|
|
|
|
|
|
def test_ids_do_not_repeat_and_survive_json():
|
|
numbers = ids.unique(stream(), 10_000)
|
|
assert numbers.dtype == np.uint64
|
|
assert len(set(numbers.tolist())) == numbers.size
|
|
assert numbers.max() < ids.LIMIT
|
|
assert numbers.min() > 0
|
|
|
|
|
|
def test_ids_do_not_give_away_the_order_of_the_rows():
|
|
"""Иначе номер события рассказывал бы, каким по счёту оно родилось."""
|
|
numbers = ids.unique(stream(), 1_000)
|
|
assert not np.all(np.diff(numbers.astype(np.int64)) > 0)
|
|
|
|
|
|
def test_ids_of_another_stream_are_other_ids():
|
|
assert not np.array_equal(ids.unique(stream(), 100), ids.unique(stream(1), 100))
|
|
|
|
|
|
def test_ids_can_be_drawn_beside_the_ones_already_taken():
|
|
"""Торговые строки берут номера из своего подпотока и не задевают чужие."""
|
|
taken = ids.unique(stream(), 5_000)
|
|
numbers = ids.unique_apart_from(stream(1), 500, taken)
|
|
assert len(set(numbers.tolist())) == numbers.size
|
|
assert not set(numbers.tolist()) & set(taken.tolist())
|
|
assert numbers.max() < ids.LIMIT
|