docs(generator): путеводитель по генератору и живой проход make demo
- Зачем:
- спека отвечает «почему», а жанра «как пройти устройство по коду»
не было (#48); черновик в generator/README.md ждал выверки.
- Что:
- новый набор docs/architecture/generator/: индекс с целевой картиной
и mermaid-схемой плюс шесть поддокументов по темам тикета.
- демо-модуль и цель make demo: канонический D0, все стадии цепочки
на одном экране; тест-сторож проверяет стадии без прибитых чисел.
- раздел «Как это работает» в generator/README.md сжат до ссылки
на путеводитель, черновая врезка снята.
- Проверка:
- из generator/: make lint, make typecheck, make test (430 passed),
make demo; два слепых ревью и узкая перепроверка — находки закрыты.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
33aef73d0e
commit
0c466c082e
11 files changed
+392
-26
No files matched your search
@@ -0,0 +1,62 @@
|
||||
"""Короткий проход по цепочке генератора на каноническом дне D0."""
|
||||
|
||||
from collections import Counter
|
||||
|
||||
import numpy as np
|
||||
|
||||
from clickstream_generator import day, plan, seeds, world
|
||||
|
||||
DAY = 0
|
||||
|
||||
|
||||
def _number(value: int) -> str:
|
||||
"""Разделяет разряды числа для чтения с экрана."""
|
||||
return f"{value:,}".replace(",", " ")
|
||||
|
||||
|
||||
def render() -> str:
|
||||
"""Собирает D0 и показывает его стадии без числового эталона."""
|
||||
seed = seeds.CANONICAL_SEED
|
||||
cohort = plan.cohort(seed, DAY)
|
||||
audience = plan.audience(seed, DAY)
|
||||
events = day.stream(seed, DAY)
|
||||
|
||||
_, rows_per_visit = np.unique(events.columns["VisitID"], return_counts=True)
|
||||
event_types = Counter(str(value) for value in events.columns["EventType"])
|
||||
smallest_visit = int(rows_per_visit.min())
|
||||
largest_visit = int(rows_per_visit.max())
|
||||
|
||||
return "\n".join(
|
||||
(
|
||||
f"Зерно: {seed}",
|
||||
"Подпотоки D0: состав мира → когорта; день → трафик, торговля, заказы",
|
||||
(
|
||||
f"Когорта D0: людей — {_number(cohort.people)}; "
|
||||
f"кук — {_number(len(cohort.client_id))}"
|
||||
),
|
||||
(
|
||||
f"Аудитория D0: кук — {_number(len(audience.client_id))}; "
|
||||
f"когорты D-{world.RETURN_TAIL_DAYS}...D0"
|
||||
),
|
||||
(
|
||||
f"Визиты по VisitID: групп — {_number(len(rows_per_visit))}; "
|
||||
f"строк в группе — {smallest_visit}–{largest_visit}"
|
||||
),
|
||||
(
|
||||
f"Строки событий: {_number(len(events))} "
|
||||
f"(pageview — {_number(event_types['pageview'])}; "
|
||||
f"add_to_cart — {_number(event_types['add_to_cart'])}; "
|
||||
f"purchase — {_number(event_types['purchase'])}); "
|
||||
f"заказов — {_number(len(events.orders))}"
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Печатает проход по D0."""
|
||||
print(render())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user