# πŸ“Š БистСма статистики Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² Полная докумСнтация ΠΏΠΎ расчёту ΠΈ использованию статистики Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² Π² Discours. ## 🎯 ΠžΠ±Π·ΠΎΡ€ БистСма статистики Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² прСдоставляСт ΠΌΠ½ΠΎΠ³ΠΎΠΌΠ΅Ρ€Π½ΡƒΡŽ ΠΎΡ†Π΅Π½ΠΊΡƒ активности, популярности ΠΈ вовлСчённости ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π°Π²Ρ‚ΠΎΡ€Π° Π½Π° ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅. ВсС ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ Ρ€Π°ΡΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΡŽΡ‚ΡΡ для ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. ## πŸ“ˆ ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ AuthorStat ```graphql # Бтатистика Π°Π²Ρ‚ΠΎΡ€Π° - полная ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ° активности ΠΈ популярности type AuthorStat { # ΠšΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π°Π²Ρ‚ΠΎΡ€Π° shouts: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Ρ… статСй topics: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Π΅ΠΌ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… участвовал comments: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ созданных ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² ΠΈ Ρ†ΠΈΡ‚Π°Ρ‚ # ВзаимодСйствиС с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Π°Π²Ρ‚ΠΎΡ€Π°ΠΌΠΈ coauthors: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… соавторов followers: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ подписчиков # РСйтинговая систСма rating: Int # ΠžΠ±Ρ‰ΠΈΠΉ Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ (rating_shouts + rating_comments) rating_shouts: Int # Π Π΅ΠΉΡ‚ΠΈΠ½Π³ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ (сумма Ρ€Π΅Π°ΠΊΡ†ΠΈΠΉ LIKE/AGREE/ACCEPT/PROOF/CREDIT минус DISLIKE/DISAGREE/REJECT/DISPROOF) rating_comments: Int # Π Π΅ΠΉΡ‚ΠΈΠ½Π³ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² (Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π°Π²Ρ‚ΠΎΡ€Π°) # ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ вовлСчённости replies_count: Int # ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² Π½Π° ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π°Π²Ρ‚ΠΎΡ€Π° (ΠΎΡ‚Π²Π΅Ρ‚Ρ‹ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ + ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π½Π° посты) viewed_shouts: Int # ΠžΠ±Ρ‰Π΅Π΅ количСство просмотров всСх ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ Π°Π²Ρ‚ΠΎΡ€Π° } ``` ### πŸ“ ΠšΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π°Π²Ρ‚ΠΎΡ€Π° #### `shouts: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Ρ… статСй** - Π£Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡΡ‚Π°Ρ‚ΡŒΠΈ со статусом `published_at IS NOT NULL` - Π˜ΡΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΡƒΠ΄Π°Π»Ρ‘Π½Π½Ρ‹Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ (`deleted_at IS NULL`) - ΠŸΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ `shout_author` ```sql SELECT sa.author, COUNT(DISTINCT s.id) as shouts_count FROM shout_author sa JOIN shout s ON sa.shout = s.id WHERE s.deleted_at IS NULL AND s.published_at IS NOT NULL GROUP BY sa.author ``` #### `topics: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Π΅ΠΌ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… участвовал Π°Π²Ρ‚ΠΎΡ€** - ΠŸΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ‚Π΅ΠΌΡ‹ Ρ‡Π΅Ρ€Π΅Π· связку статСй Π°Π²Ρ‚ΠΎΡ€Π° - Основано Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ… `shout_author` β†’ `shout_topic` ```sql SELECT sa.author, COUNT(DISTINCT st.topic) as topics_count FROM shout_author sa JOIN shout s ON sa.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL JOIN shout_topic st ON s.id = st.shout GROUP BY sa.author ``` #### `comments: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ созданных ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² ΠΈ Ρ†ΠΈΡ‚Π°Ρ‚** - Π’ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ Ρ‚ΠΈΠΏΠ° `COMMENT` ΠΈ `QUOTE` - Π˜ΡΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΡƒΠ΄Π°Π»Ρ‘Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ```sql SELECT r.created_by, COUNT(DISTINCT r.id) as comments_count FROM reaction r JOIN shout s ON r.shout = s.id AND s.deleted_at IS NULL WHERE r.deleted_at IS NULL AND r.kind IN ('COMMENT', 'QUOTE') GROUP BY r.created_by ``` ### πŸ‘₯ ВзаимодСйствиС с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Π°Π²Ρ‚ΠΎΡ€Π°ΠΌΠΈ #### `coauthors: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… соавторов** - ΠŸΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Π°Π²Ρ‚ΠΎΡ€ΠΎΠ², с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ Π°Π²Ρ‚ΠΎΡ€ ΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π» совмСстныС ΡΡ‚Π°Ρ‚ΡŒΠΈ - Π˜ΡΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ самого Π°Π²Ρ‚ΠΎΡ€Π° ΠΈΠ· подсчёта - Π£Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΈ Π½Π΅ΡƒΠ΄Π°Π»Ρ‘Π½Π½Ρ‹Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ ```sql SELECT sa1.author, COUNT(DISTINCT sa2.author) as coauthors_count FROM shout_author sa1 JOIN shout s ON sa1.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL JOIN shout_author sa2 ON s.id = sa2.shout AND sa2.author != sa1.author -- ΠΈΡΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ самого Π°Π²Ρ‚ΠΎΡ€Π° GROUP BY sa1.author ``` #### `followers: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ подписчиков** - ΠŸΡ€ΡΠΌΠΎΠΉ подсчёт ΠΈΠ· Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ `author_follower` ```sql SELECT following, COUNT(DISTINCT follower) as followers_count FROM author_follower GROUP BY following ``` ### ⭐ РСйтинговая систСма #### `rating: Int` **ΠžΠ±Ρ‰ΠΈΠΉ Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ Π°Π²Ρ‚ΠΎΡ€Π°** - Π‘ΡƒΠΌΠΌΠ° `rating_shouts + rating_comments` - АгрСгированная ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ° популярности ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° #### `rating_shouts: Int` **Π Π΅ΠΉΡ‚ΠΈΠ½Π³ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ Π°Π²Ρ‚ΠΎΡ€Π°** - Π‘ΡƒΠΌΠΌΠ° всСх Ρ€Π΅Π°ΠΊΡ†ΠΈΠΉ Π½Π° ΡΡ‚Π°Ρ‚ΡŒΠΈ Π°Π²Ρ‚ΠΎΡ€Π° - ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ: `LIKE`, `AGREE`, `ACCEPT`, `PROOF`, `CREDIT` (+1) - ΠžΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ: `DISLIKE`, `DISAGREE`, `REJECT`, `DISPROOF` (-1) - ΠΠ΅ΠΉΡ‚Ρ€Π°Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ: ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ (0) ```sql SELECT sa.author, SUM(CASE WHEN r.kind IN ('LIKE', 'AGREE', 'ACCEPT', 'PROOF', 'CREDIT') THEN 1 WHEN r.kind IN ('DISLIKE', 'DISAGREE', 'REJECT', 'DISPROOF') THEN -1 ELSE 0 END) as rating_shouts FROM shout_author sa JOIN shout s ON sa.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL JOIN reaction r ON s.id = r.shout AND r.deleted_at IS NULL GROUP BY sa.author ``` #### `rating_comments: Int` **Π Π΅ΠΉΡ‚ΠΈΠ½Π³ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² Π°Π²Ρ‚ΠΎΡ€Π°** - Аналогичная систСма для Ρ€Π΅Π°ΠΊΡ†ΠΈΠΉ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π°Π²Ρ‚ΠΎΡ€Π° - ΠŸΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Ρ‡Π΅Ρ€Π΅Π· `reply_to` ```sql SELECT r1.created_by, SUM(CASE WHEN r2.kind IN ('LIKE', 'AGREE', 'ACCEPT', 'PROOF', 'CREDIT') THEN 1 WHEN r2.kind IN ('DISLIKE', 'DISAGREE', 'REJECT', 'DISPROOF') THEN -1 ELSE 0 END) as rating_comments FROM reaction r1 JOIN reaction r2 ON r1.id = r2.reply_to AND r2.deleted_at IS NULL WHERE r1.deleted_at IS NULL AND r1.kind IN ('COMMENT', 'QUOTE') GROUP BY r1.created_by ``` ### πŸ”„ ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ вовлСчённости #### `replies_count: Int` **ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² Π½Π° ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π°Π²Ρ‚ΠΎΡ€Π°** - **КомплСксная ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ°**, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π°Ρ: 1. **ΠžΡ‚Π²Π΅Ρ‚Ρ‹ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π°Π²Ρ‚ΠΎΡ€Π°** (Ρ‡Π΅Ρ€Π΅Π· `reply_to`) 2. **ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π½Π° посты Π°Π²Ρ‚ΠΎΡ€Π°** (прямыС ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ΠΊ ΡΡ‚Π°Ρ‚ΡŒΡΠΌ) Π›ΠΎΠ³ΠΈΠΊΠ° расчёта: ```python # ΠžΡ‚Π²Π΅Ρ‚Ρ‹ Π½Π° ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ replies_to_comments = COUNT(r2) WHERE r1.created_by = author AND r2.reply_to = r1.id # ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Π½Π° посты comments_on_posts = COUNT(r) WHERE sa.author = author AND r.shout = s.id # Π˜Ρ‚ΠΎΠ³ΠΎ replies_count = replies_to_comments + comments_on_posts ``` #### `viewed_shouts: Int` **ΠžΠ±Ρ‰Π΅Π΅ количСство просмотров всСх ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ Π°Π²Ρ‚ΠΎΡ€Π°** - Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ с `ViewedStorage` (Google Analytics) - Π‘ΡƒΠΌΠΌΠΈΡ€ΡƒΠ΅Ρ‚ просмотры всСх статСй Π°Π²Ρ‚ΠΎΡ€Π° - ΠžΠ±Π½ΠΎΠ²Π»ΡΠ΅Ρ‚ΡΡ асинхронно ΠΈΠ· Π²Π½Π΅ΡˆΠ½ΠΈΡ… источников ## πŸ” API использования ### GraphQL запрос ```graphql query LoadAuthors($by: AuthorsBy, $limit: Int, $offset: Int) { load_authors_by(by: $by, limit: $limit, offset: $offset) { id slug name bio pic stat { shouts topics coauthors followers rating rating_shouts rating_comments comments replies_count viewed_shouts } } } ``` ### ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ сортировки ```graphql # Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΏΠΎ количСству ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΉ { "order": "shouts" } # Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΏΠΎ ΠΎΠ±Ρ‰Π΅ΠΌΡƒ Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³Ρƒ { "order": "rating" } # Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΏΠΎ вовлСчённости { "order": "replies_count" } # Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΏΠΎ просмотрам { "order": "viewed_shouts" } ``` ## ⚑ ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ### ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ - **Redis кСш** для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² запросов - **ΠšΠ»ΡŽΡ‡ΠΈ кСша**: `authors:stats:limit={limit}:offset={offset}:order={order}` - **TTL**: НастраиваСтся Π² `cache.py` ### ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ SQL - **Batch запросы** для получСния статистики всСх Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ - **ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½Π½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹** для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ ΠΎΡ‚ SQL-ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠΉ - **Π˜Π½Π΄Π΅ΠΊΡΡ‹** Π½Π° ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… полях (`author_id`, `shout_id`, `reaction.kind`) ### Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° - **SQL-ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ сортировки** для ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊ статистики - **ΠŸΠΎΠ΄Π·Π°ΠΏΡ€ΠΎΡΡ‹ с JOIN** для ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ - **COALESCE** для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ NULL Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ## πŸ§ͺ ВСстированиС ### Unit тСсты ```python # ВСстированиС расчёта статистики async def test_author_stats_calculation(): # Π‘ΠΎΠ·Π΄Π°Ρ‘ΠΌ тСстовыС Π΄Π°Π½Π½Ρ‹Π΅ # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ расчёта ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ pass # ВСстированиС сортировки async def test_author_sorting(): # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ сортировку ΠΏΠΎ Ρ€Π°Π·Π½Ρ‹ΠΌ полям pass ``` ### Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ тСсты - ВСстированиС с Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ - ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π½Π° Π±ΠΎΠ»ΡŒΡˆΠΈΡ… ΠΎΠ±ΡŠΡ‘ΠΌΠ°Ρ… - Валидация ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ## πŸ”§ ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ ### ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния ```bash # Google Analytics для просмотров GOOGLE_KEYFILE_PATH=/path/to/service-account.json GOOGLE_PROPERTY_ID=your-property-id # Redis для ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ REDIS_URL=redis://localhost:6379 ``` ### Настройки Ρ€Π΅Π°ΠΊΡ†ΠΈΠΉ Π’ΠΈΠΏΡ‹ Ρ€Π΅Π°ΠΊΡ†ΠΈΠΉ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π² `orm/reaction.py`: ```python # ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ (+1) POSITIVE_REACTIONS = ["LIKE", "AGREE", "ACCEPT", "PROOF", "CREDIT"] # ΠžΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ (-1) NEGATIVE_REACTIONS = ["DISLIKE", "DISAGREE", "REJECT", "DISPROOF"] ``` ## πŸš€ Π Π°Π·Π²ΠΈΡ‚ΠΈΠ΅ ### ΠŸΠ»Π°Π½ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ - [ ] Π˜ΡΡ‚ΠΎΡ€ΠΈΡ‡Π΅ΡΠΊΠΈΠ΅ Ρ‚Ρ€Π΅Π½Π΄Ρ‹ статистики - [ ] БСгмСнтация ΠΏΠΎ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄Π°ΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ - [ ] Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ вовлСчённости - [ ] ΠŸΠ΅Ρ€ΡΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ Π½Π° основС статистики ### Π˜Π·Π²Π΅ΡΡ‚Π½Ρ‹Π΅ ограничСния - ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Ρ‹ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡŽΡ‚ΡΡ с Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ (Google Analytics API) - Π‘ΠΎΠ»ΡŒΡˆΠΈΠ΅ ΠΎΠ±ΡŠΡ‘ΠΌΡ‹ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠ³ΡƒΡ‚ Π·Π°ΠΌΠ΅Π΄Π»ΡΡ‚ΡŒ запросы Π±Π΅Π· кСша - Π‘Π»ΠΎΠΆΠ½Ρ‹Π΅ запросы сортировки Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ большС рСсурсов