81 lines
2.9 KiB
Python
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,
|
|
}
|