LichessStatTgWeb/LichessClientTG_bot/formatters.py

172 lines
7.1 KiB
Python
Raw Normal View History

from typing import Dict, Any, Optional
from datetime import datetime
2025-11-12 23:20:01 +03:00
from i18n import t
class StatsFormatter:
@staticmethod
def _format_rating_change(rating_change: int) -> str:
"""Format rating change with colored circles"""
if rating_change > 0:
return f"🟢 +{rating_change}"
elif rating_change < 0:
return f"🔴 {rating_change}"
else:
return f"0"
@staticmethod
2025-11-12 23:20:01 +03:00
def format_stats_response(data: Dict[str, Any], username: str, period: str, lang: str = 'en') -> str:
"""Format statistics response according to the template"""
if not data or data.get('data') is None:
2025-11-12 23:20:01 +03:00
message = data.get('message', t('no_data', lang)) if data else t('no_data', lang)
return f"📭 {message}"
# Extract data from API response
api_data = data.get('data', {})
tasks = api_data.get('tasks', {})
games = api_data.get('games', {})
# Format date range
2025-11-12 23:20:01 +03:00
date_range = StatsFormatter._get_date_range(period, lang)
# Format tasks section
task_text = ""
if tasks and tasks.get('total', 0) > 0:
total_tasks = tasks.get('total', 0)
solved = tasks.get('solved', 0)
unsolved = tasks.get('unsolved', 0)
2025-11-12 23:20:01 +03:00
task_text = t('puzzles_section', lang, total=total_tasks, solved=solved, unsolved=unsolved)
# Format games section
games_text = ""
if games:
for game_type, game_data in games.items():
if not game_data or game_data.get('games_played', 0) == 0:
continue
# Get game type emoji
emoji = StatsFormatter._get_game_type_emoji(game_type)
games_count = game_data.get('games_played', 0)
rating_change = game_data.get('rating_change', 0)
rating = game_data.get('final_rating', 0)
wins = game_data.get('wins', 0)
losses = game_data.get('losses', 0)
draws = game_data.get('draws', 0)
# Format rating change
rating_change_str = StatsFormatter._format_rating_change(rating_change)
2025-11-12 23:20:01 +03:00
# Get game type name (capitalize first letter)
game_type_name = game_type.title()
games_text += t('games_section', lang,
emoji=emoji,
game_type=game_type_name,
games_count=games_count,
rating_change=rating_change_str,
rating=rating,
wins=wins,
losses=losses,
draws=draws
)
# Combine all parts
2025-11-12 23:20:01 +03:00
result = t('stats_title', lang, username=username, date_range=date_range)
result += task_text
result += games_text.rstrip()
return result
@staticmethod
2025-11-12 23:20:01 +03:00
def _get_date_range(period: str, lang: str = 'en') -> str:
"""Get date range string for the period"""
from datetime import datetime, timedelta
today = datetime.now()
if period == "today":
return today.strftime("%d.%m.%Y")
elif period == "yesterday":
yesterday = today - timedelta(days=1)
return yesterday.strftime("%d.%m.%Y")
elif period == "week":
week_ago = today - timedelta(days=7)
return f"{week_ago.strftime('%d.%m.%Y')}{today.strftime('%d.%m.%Y')}"
else:
return today.strftime("%d.%m.%Y")
@staticmethod
def _get_game_type_emoji(game_type: str) -> str:
"""Get emoji for game type"""
emoji_map = {
'bullet': '⚡️',
'blitz': '🔥',
'rapid': '🐇',
'classical': '♟️',
'correspondence': '📮'
}
return emoji_map.get(game_type.lower(), '🎯')
@staticmethod
2025-11-12 23:20:01 +03:00
def format_period_notification(username: str, games_data: Optional[Dict], puzzles_data: Optional[Dict], period_minutes: int, lang: str = 'en') -> str:
"""Format notification for periodic checks"""
from datetime import datetime
# Format period text
if period_minutes == 1:
2025-11-12 23:20:01 +03:00
period_text = t('period_1_minute', lang)
elif period_minutes in [2, 3, 4]:
2025-11-12 23:20:01 +03:00
period_text = t('period_2_3_4_minutes', lang, period=period_minutes)
else:
2025-11-12 23:20:01 +03:00
period_text = t('period_minutes_text', lang, period=period_minutes)
2025-11-12 23:20:01 +03:00
result = t('period_notification_title', lang, username=username, period_text=period_text)
# Format puzzles first (if available and there's actual activity)
if puzzles_data and puzzles_data.get('data'):
puzzles_info = puzzles_data['data']
total_puzzles = puzzles_info.get('total_attempts', 0)
solved = puzzles_info.get('solved', 0)
failed = puzzles_info.get('failed', 0)
# Only show tasks section if there's actual activity (not all zeros)
if total_puzzles > 0 or solved > 0 or failed > 0:
2025-11-12 23:20:01 +03:00
result += t('period_puzzles_section', lang, total=total_puzzles, solved=solved, failed=failed)
# Format games
if games_data and games_data.get('data'):
games_info = games_data['data']
total_games = games_info.get('total', {}).get('games_played', 0)
# Show details for each game type if there were games
if total_games > 0:
for game_type, game_data in games_info.items():
if game_type != 'total' and game_data and game_data.get('games_played', 0) > 0:
emoji = StatsFormatter._get_game_type_emoji(game_type)
games_count = game_data.get('games_played', 0)
rating_change = game_data.get('rating_change', 0)
rating = game_data.get('rating', 0)
wins = game_data.get('wins', 0)
losses = game_data.get('losses', 0)
draws = game_data.get('draws', 0)
rating_change_str = StatsFormatter._format_rating_change(rating_change)
2025-11-12 23:20:01 +03:00
game_type_name = game_type.title()
result += t('period_games_section', lang,
emoji=emoji,
game_type=game_type_name,
games_count=games_count,
rating_change=rating_change_str,
rating=rating,
wins=wins,
losses=losses,
draws=draws
)
# If no activity
if not (games_data and games_data.get('data')) and not (puzzles_data and puzzles_data.get('data')):
2025-11-12 23:20:01 +03:00
result += t('no_activity', lang)
return result.rstrip()