From 1ff4012e2f65c9bc8e17120a6acd9fdb52e00c4f Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 20 Oct 2026 18:35:39 +0200 Subject: [PATCH] feat: show analytics across periods in tables --- VERSION | 2 +- analytics.py | 43 +++++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/VERSION b/VERSION index 216edd8..1ae380f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0+66 +0.1.0+67 diff --git a/analytics.py b/analytics.py index 46070d6..cf18871 100644 --- a/analytics.py +++ b/analytics.py @@ -134,23 +134,30 @@ def _html_table(headers: list[str], rows: list[list[object]]) -> str: def render_report(period: str = "all", db_path: str | None = None) -> str: - metrics = all_metrics(period, db_path) - types = metrics["message_types"] - generation_types = {k[1]: v for k, v in types.items() if k[0] == "generation"} - training_types = {k[1]: v for k, v in types.items() if k[0] == "training"} - users = metrics["users"] - active = metrics["active_users"] - user_rows = [["Всего", users], ["Активные", active]] - activity_rows = [["Генерации постов", metrics["post_generations"]], ["Идеи", metrics["idea_generations"]], ["Правки постов", metrics["post_revisions"]], ["Сообщения", metrics["generation_messages"]]] - generation_type_rows = [[key, value] for key, value in sorted(generation_types.items())] or [["Нет данных", 0]] - training_type_rows = [[key, value] for key, value in sorted(training_types.items())] or [["Нет данных", 0]] - training_rows = [["Сообщения", metrics["training_messages"]]] + labels = {"day": "Сегодня", "week": "7 дней", "month": "30 дней", "all": "Всё время"} + metrics_by_period = {key: all_metrics(key, db_path) for key in labels} + titles = ["Сегодня", "7 дней", "30 дней", "Всё время"] + + def table(title: str, metric_rows: list[tuple[str, str]]) -> str: + rows = [[label, *(metrics_by_period[key][metric] for key in labels)] for label, metric in metric_rows] + return "

" + title + "

" + _html_table(["Показатель", *titles], rows) + + def table(title: str, metric_rows: list[tuple[str, str]]) -> str: + rows = [[label, *(metrics_by_period[key][metric] for key in labels)] for label, metric in metric_rows] + return "

" + title + "

" + _html_table(["Показатель", *titles], rows) + + type_names = sorted({key[1] for metrics in metrics_by_period.values() for key in metrics["message_types"]}) + generation_rows = [[kind, *(metrics_by_period[p]["message_types"].get(("generation", kind), 0) for p in labels)] for kind in type_names] + training_type_rows = [[kind, *(metrics_by_period[p]["message_types"].get(("training", kind), 0) for p in labels)] for kind in type_names] + if not generation_rows: + generation_rows = [["Нет данных", 0, 0, 0, 0]] + training_type_rows = [["Нет данных", 0, 0, 0, 0]] + return ( - "

📊 Полная статистика бота

" - f"

Период: {period}

" - "

Пользователи

" + _html_table(["Показатель", "Количество"], user_rows) - + "

Генерация

" + _html_table(["Показатель", "Количество"], activity_rows) - + "

Типы сообщений в генерации

" + _html_table(["Тип", "Количество"], generation_type_rows) - + "

Обучение

" + _html_table(["Показатель", "Количество"], training_rows) - + "

Типы сообщений в обучении

" + _html_table(["Тип", "Количество"], training_type_rows) + "

📊 Статистика бота

" + + table("Пользователи", [("Активные", "active_users")]) + + table("Генерация", [("Посты", "post_generations"), ("Идеи", "idea_generations"), ("Правки", "post_revisions"), ("Сообщения", "generation_messages")]) + + "

Типы сообщений в генерации

" + _html_table(["Тип", *titles], generation_rows) + + table("Обучение", [("Сообщения", "training_messages")]) + + "

Типы сообщений в обучении

" + _html_table(["Тип", *titles], training_type_rows) )