"""Конфигурация мира: все числа, которыми задан модельный магазин. Модуль — приглашение крутить: поменяйте число, пересоберите снимок и посмотрите, что стало с данными. Правка любой константы здесь — смена мира, поэтому чек манифеста честно покраснеет: манифест сторожит только канонический мир, свои миры менти собирает без его гарантий (спека генератора, раздел 9). Числа решены спекой и связаны между собой; связки сторожат тесты `test_world.py`, чтобы правка одного числа не рассыпала вывод соседнего. Здесь только чистые данные — как в контракте схемы, никакой логики. """ from datetime import date # D0 — первый день оси модельного времени, понедельник. Реальный календарь в # модели не участвует: дата нужна лишь затем, чтобы дни оси легли в # `EventDate`/`UTCEventTime` конкретными числами. От даты запуска мир не # зависит — иначе манифест перестал бы быть воспроизводимым. ORIGIN = date(2026, 6, 1) # Приток: сколько новых людей приходит в мир в средний день. Каждый приводит # свою куку, поэтому число это же — приток кук; вторые куки двухкуковых пар # добавляют к нему меньше процента. DAILY_INFLUX = 3_800 # Недельная волна притока, проценты от среднего: понедельник … воскресенье. # Модулируется тем же профилем, что трафик, — иначе доля новичков скакала бы # по дням недели. В сумме ровно 700: за неделю средний день остаётся средним. WEEKLY_INFLUX_PERCENT = (105, 108, 107, 105, 95, 88, 92) # Разброс притока изо дня в день, проценты: ровный приток выдал бы себя в # первом же графике по дням. INFLUX_JITTER_PERCENT = 5 # Доля одноразовых кук: пришли раз и не вернулись — как в живом трафике. ONE_SHOT_PERCENT = 75 # Сколько раз возвращается кука, которая вернулась хоть раз: веса для 1, 2, # 3 … возвратов. В среднем выходит 3–4 возврата; вместе с одноразовыми это # ≈1,9 активного дня на куку — отсюда дневная аудитория 6–8 тыс. при # притоке 3 800 (спека, разделы 5 и 9). RETURN_COUNT_WEIGHTS = (25, 20, 15, 12, 9, 7, 5, 4, 2, 1) # Хвост возвратов: окно активности куки от её первого визита. За краем окна # кука не возвращается. Оно же — глубина предыстории: столько когорт живёт # до D0, чтобы дневная аудитория была на полке с самого первого дня. RETURN_TAIL_DAYS = 90 # Профиль возвратов по дням от первого визита: почти всё в первую неделю, # дальше тонкий хвост до края окна — повторные покупки в магазине случаются # и через месяцы. Профиль затухает к краю, поэтому обрыв на нём в данных не # виден. Читается по парам «сколько дней — с каким весом»; дней в сумме # ровно `RETURN_TAIL_DAYS`. RETURN_DELAY_WEIGHTS = tuple( weight for days, weight in ((3, 100), (7, 40), (20, 8), (60, 1)) for _ in range(days) ) # Доля покупателей среди людей когорты. Считается людьми, не куками: человек # с двумя куками — один покупатель. Число плана, а не торгового поведения: # без него не отобрать двухкуковые пары. BUYER_PERCENT = 5 # Доля покупателей, у которых заведётся вторая кука (мастер-спека, раздел 5). # Такой паре план назначает по гарантированному заказу с каждой куки — на # этом стоит лаба про склейку личности. PAIRED_BUYER_PERCENT = 15