Files
mp-answer-bot/app/services/stats.py

81 lines
2.9 KiB
Python

import logging
from datetime import datetime, time
from app import config
from app.models import Review
logger = logging.getLogger(__name__)
class StatsService:
async def get_daily_stats(self, platform: str) -> dict:
target_date = datetime.now(config.TIMEZONE).date()
day_start = datetime.combine(target_date, time.min, tzinfo=config.TIMEZONE)
day_end = datetime.combine(target_date, time.max, tzinfo=config.TIMEZONE)
reviews = await Review.filter(
platform=platform, published_at__gte=day_start, published_at__lte=day_end
)
return self._calculate_stats(platform, reviews)
async def get_all_time_stats(self, platform: str) -> dict:
reviews = await Review.filter(platform=platform)
return self._calculate_stats(platform, reviews)
def _calculate_stats(self, platform: str, reviews: list) -> dict:
good_reviews = 0
bad_reviews = 0
critical_reviews = 0
rating_counts = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
tone_counts = {"positive": 0, "neutral": 0, "negative": 0}
for review in reviews:
rating = min(max(review.rating, 1), 5)
rating_counts[rating] += 1
if rating <= 3:
bad_reviews += 1
if review.is_critical:
critical_reviews += 1
else:
good_reviews += 1
if review.tone in tone_counts:
tone_counts[review.tone] += 1
total_reviews = good_reviews + bad_reviews
bad_ratio = bad_reviews / total_reviews if total_reviews > 0 else 0
critical_ratio = critical_reviews / total_reviews if total_reviews > 0 else 0
critical_to_bad_ratio = critical_reviews / bad_reviews if bad_reviews > 0 else 0
total_ratings = sum(rating_counts.values())
weighted_sum = sum(count * rating for rating, count in rating_counts.items())
average_rating = weighted_sum / total_ratings if total_ratings > 0 else 0
return {
"platform": platform,
"good_reviews": good_reviews,
"bad_reviews": bad_reviews,
"total_reviews": total_reviews,
"bad_ratio": bad_ratio,
"critical_reviews": critical_reviews,
"critical_ratio": critical_ratio,
"critical_to_bad_ratio": critical_to_bad_ratio,
"ratings": {
"1": rating_counts[1],
"2": rating_counts[2],
"3": rating_counts[3],
"4": rating_counts[4],
"5": rating_counts[5],
},
"tone": {
"positive": tone_counts["positive"],
"neutral": tone_counts["neutral"],
"negative": tone_counts["negative"],
},
"average_rating": average_rating,
}