# Кликстрим-платформа (стенд v2) Словарь понятий, которые встречаются в учебных заданиях, документации и коде стенда. ## Язык - [Люди и события](#люди-и-события) - [Хранилище и форматы данных](#хранилище-и-форматы-данных) - [Заказы](#заказы) - [Модельное время и запуск стенда](#модельное-время-и-запуск-стенда) - [Устройство генератора](#устройство-генератора) — для чтения его кода и технических справочников. ### Люди и события **Человек**: Участник модели магазина, который может заходить с одного или двух устройств. Генератор знает, какие идентификаторы посетителя ему принадлежат, но в событиях сайта этой связи нет. **Посетитель**: Браузер на устройстве, который счетчик сайта узнает по куке — сохраненному в браузере идентификатору. В кликстриме он обозначается `ClientID`: `uniq(ClientID)` считает посетителей, и у одного человека их может быть несколько. _Избегать_: «посетитель» про человека после объединения его идентификаторов. **Пользователь магазина**: Человек, известный серверной части магазина под идентификатором `user_id`. Он указан в заказах и позволяет связать разные `ClientID` одного человека; в кликстриме поля `user_id` нет. Например, покупки с телефона и ноутбука могут иметь разные `ClientID`, но один `user_id` в заказах. **Визит**: Последовательность событий одного посетителя без пауз длиннее 30 минут и без перехода через полночь по часовому поясу счетчика. Сессия означает то же самое; поле `VisitID` служит эталоном в задании по нарезке сессий. **День активности**: День, в который посетитель появился на сайте хотя бы раз: впервые или вернувшись. За один день активности у него может быть несколько визитов. _Избегать_: визит в значении целого дня активности. **Паспорт куки**: Устройство и город, закрепленные за посетителем во все дни его активности. Генератор записывает их в поля событий. У двух посетителей одного человека город совпадает, а устройства различаются. **Торговое событие**: Запись о добавлении товара в корзину или о покупке: `add_to_cart` или `purchase`. Это отдельная строка кликстрима со страницей, где произошло действие: карточкой товара для корзины или страницей подтверждения для покупки. ### Хранилище и форматы данных **Хранилище**: Аналитическая база стенда в ClickHouse. Данные проходят слои STG, ODS, DDS и DM: от исходных сообщений до витрин для отчетов. Хранилище принимает данные по документации источников и приводит их к своей модели и именам. _Избегать_: склад, склад данных. **Сырые данные**: Исходные сообщения Kafka, сохраненные в слое STG без разбора: одно сообщение занимает одну строку таблицы. Слой STG также называют сырым слоем. _Избегать_: сырьё. **Справочник**: Готовые сведения из внешнего источника, которыми хранилище дополняет свои данные. На стенде они находятся в базе `dic`; пока это только каталог товаров. Объект `DICTIONARY` ClickHouse — одна из форм доступа к справочнику. _Избегать_: словарь в значении справочных данных: это слово уже обозначает `DICTIONARY` и словарь понятий. **Каталог товаров**: Список товаров с артикулами, названиями, категориями, брендами, ценами и уровнями спроса. Файл `data/catalog/products.csv` общий для генератора и справочника ClickHouse; товары можно добавлять строками в этом формате. **Нормализованное имя**: Имя поля источника, записанное в стиле `snake_case`: например, `ClientID` становится `client_id`. Оно указано в описании выгрузки и контракте схемы. Слой DDS выбирает имена по своей модели данных, поэтому они не обязаны повторять нормализованные имена источника. **Описание выгрузки**: Документ, который объясняет поля и формат событий источника: [`docs/formats/clickstream-event.md`](docs/formats/clickstream-event.md). По нему строится прием данных в хранилище. Документ собирается из описаний колонок генератора: правят их, затем пересобирают документ. _Избегать_: описание схемы, документация контракта. **Техническая проверка**: Проверка по внутреннему эталону стенда, например сравнение числа событий с паспортом мира. Проверка качества данных (DQ) опирается на данные магазина и связи между ними; ей не нужен эталон генератора, которого у настоящего магазина нет. _Избегать_: DQ-проверка в значении проверки по паспорту мира. ### Заказы **Слепок**: Дневная выгрузка состояния заказов из серверной части магазина. Она содержит заказы, оформленные за последние семь модельных дней, с учетом изменений к концу дня. Опоздавший заказ может отсутствовать в первых слепках. **Дата слепка**: Дата модельного дня, на конец которого снято состояние заказов; поле `snapshot_date` одинаково во всех строках выгрузки. Даты оформления заказов могут различаться; выгрузка отправляется на следующий модельный день. **Время аудита источника**: Время создания и последнего изменения записи заказа по часам базы магазина: поля `created_at` и `updated_at`. Время покупки в событии `purchase` записывает счетчик сайта, и оно может отличаться от этих полей. **Окно изменяемости**: Семь модельных дней, включая день оформления, в течение которых заказ может измениться и входит в слепки. После этого его состояние окончательно. Например, заказ от 1 июня входит в окно слепков за 1–7 июня; опоздание сокращает число его появлений, но не сдвигает конец окна. **Пакетный забор**: Чтение сообщений Kafka отдельным запросом по команде. Так хранилище принимает заказы после отправки всего слепка. События сайта оно принимает непрерывно через материализованное представление. _Избегать_: смешивать с пакетным режимом генератора: забор — чтение на стороне хранилища, режим генератора — отправка. ### Модельное время и запуск стенда **Мир**: Модель интернет-магазина: люди, их посещения сайта, товары и заказы, которые создает генератор. **Ось модельного времени**: Календарь магазина в генераторе. Первый день, D0, — 1 июня 2026 года, понедельник (`world.ORIGIN`); следующие дни отсчитываются от него. Реальное время — часы компьютера, на котором работает стенд. Дата запуска не меняет даты событий: D0 остается 1 июня, даже если стенд запущен осенью. **Граница суток**: Конец одного модельного дня и начало следующего, полночь по часовому поясу счетчика. Здесь заканчиваются визиты и снимается состояние заказов для слепка. Даги времени продвигают мир только на целые дни. **Стартовый мир**: Данные первых восьми модельных дней, с понедельника по следующий понедельник, которыми стенд наполняется при первом `make up`. Команда вызывает `world_initialize`: если мир уже готов и сохранен, повторный запуск оставляет данные и позицию времени прежними. `make rebuild-storage` пересоздает стартовый мир. При неизменных коде, каталоге и настройках его данные повторяются и служат эталоном проверок. _Избегать_: зерновой мир. **Паспорт мира**: Файл для сверки с эталонными данными: `data/world-inventory.json`. В нем записаны зерно генерации, версия генератора, контрольная сумма каталога, число событий и контрольная сумма каждого начального дня, контрольные суммы слепков и счетчики расхождений по заказам. В git хранится паспорт; сами события и слепки пересчитываются генератором. _Избегать_: опись мира, манифест, мини-манифест. **Пошаговый режим**: Продвижение модельного времени по явной команде: запустить генерацию следующего дня или нескольких дней. **Пакетный режим**: Отправка событий готового модельного дня без пауз между ними. Используется для начального наполнения, пересборок и проверок. **Живой день**: Постепенная отправка событий по времени их появления в модельном дне, с ускорением: по умолчанию сутки занимают около 24 реальных минут. Чтобы следующие дни запускались автоматически, снимают с паузы `world_live`. **Даги модельного времени**: Наборы связанных задач Airflow для генерации следующих дней магазина: `world_next_day`, `world_live_day` и `world_live`. Первые два выполняют шаг по времени, третий автоматически запускает живые дни, пока снят с паузы. Короткое название — даги времени. _Избегать_: пульт мира, управляющие даги. **Шаговый даг**: Даг, который отправляет данные следующих модельных дней и после успеха записывает новую позицию времени. `world_next_day` отправляет их пачкой, `world_live_day` — один день с ускорением. У них нет расписания; их запускают вручную или из другого дага. _Избегать_: работник. ### Устройство генератора **Зерно генерации**: Число, которое задает повторяемую последовательность случайных выборов генератора. Одинаковые зерно и день дают одинаковые данные при неизменных коде, каталоге и настройках. Эталон использует `CANONICAL_SEED` из `seeds.py`. **Состав мира**: Люди в модели, их идентификаторы посетителей и заранее заданные привычки: когда они приходят, как часто возвращаются, склонны ли покупать. У части людей две куки — это двухкуковые пары. _Избегать_: состояние мира. **План состава**: Расчет того, какие посетители придут в каждый день и какие свойства у них будут. В `plan.py` из зерна и номера дня получаются новые посетители, их возвраты и назначенные заказы людей с двумя куками. **Когорта дня**: Группа людей, впервые пришедших в один день, со всеми их куками и днями активности. Генератор рассчитывает ее по зерну и номеру первого дня. **Приток**: Появление новых посетителей (`ClientID`) по мере продвижения модельного времени. Поэтому число разных посетителей за весь период растет и не совпадает с числом посетителей за отдельный день. **Хвост возвратов**: Срок от первого появления человека, в пределах которого его куки могут возвращаться на сайт. У человека с двумя куками конец срока общий. **Предыстория**: Люди, впервые пришедшие до D0, и план их активности. До D0 события не создаются; возвраты этих людей дают повторных посетителей уже в первый день генерируемых данных. **Покупатель**: Человек, которому генератор заранее назначил повышенную склонность покупать. Он чаще доходит до заказа, но иногда покупают и остальные. Из таких людей выбираются те, у кого будут две куки. _Избегать_: покупатель в значении любого посетителя с покупкой за день; для этого случая — «визит с заказом». **Уровень спроса**: Свойство товара, от которого зависит, как часто после просмотра карточки его добавляют в корзину. В колонке `demand` каталога три значения: `магнит`, `обычный`, `залёживается`. Они постоянны по дням и задают различия в конверсии товаров и брендов. **Конфигурация мира**: Числовые настройки модели магазина в `world.py`: приток, частота возвратов, доли покупателей, начальная дата и другие параметры. Изменение этих настроек меняет генерируемые данные. **Подпоток**: Отдельная последовательность случайных выборов для части генератора, например для торговли в заданный день. В `seeds.py` она определяется общим зерном, днем и компонентом; для состава мира есть отдельные последовательности. Результат не зависит от порядка расчета частей. **День-функция**: Расчет событий одних модельных суток по зерну и номеру дня, без генерации предыдущих дней. Функция `day.stream(seed, day)` возвращает события в порядке времени. **Судьба заказа**: Заранее рассчитанные изменения заказа: итоговый статус, время оплаты или отмены, удаленная позиция и задержка первого появления в слепке. Они укладываются в семидневное окно заказа. Слепок показывает состояние на выбранный день без проигрывания предыдущих изменений. **Контракт схемы**: Описания колонок события в модуле генератора `schema.py`: имена, типы и ограничения. По ним генератор создает и проверяет события, а `schema_doc.py` собирает описание выгрузки для хранилища. **Канонический сериализатор**: Код в `serialize.py`, который превращает события и записи заказов в JSON для отправки. Порядок ключей и формат значений фиксированы, поэтому одинаковые записи дают одинаковые байты. **Проигрыватель**: Код в `player.py`, который доставляет готовые события дня в приемник, например в Kafka или файл. В пакетном режиме он отправляет их без пауз, в режиме живого дня — с ускорением по времени событий.