Code cleanup: standardized imports, refined formatting for consistency, and resolved minor redundancies in services, models, monitoring, and tools modules.

This commit is contained in:
Yûki VACHOT 2025-11-29 00:49:36 +01:00
parent e486d78e31
commit ec0fe38861
39 changed files with 222 additions and 239 deletions

View file

@ -1,12 +1,12 @@
"""Services module for business logic."""
from .profile_service import ProfileService
from .game_service import GameService
from .analysis_service import AnalysisService, GameAnalysis
from .game_service import GameService
from .profile_service import ProfileService
__all__ = [
"ProfileService",
"GameService",
"AnalysisService",
"GameAnalysis",
]
]

View file

@ -21,6 +21,7 @@ logger = logging.getLogger(__name__)
@dataclass
class GameAnalysis:
"""Analysis results for a set of games."""
games_analyzed: int = 0
total_score: int = 0
average_score: float = 0.0
@ -88,15 +89,9 @@ class AnalysisService:
# Calculate averages
avg_distance = (
sum(r.distance_meters for r in all_rounds) / total_rounds
if total_rounds > 0
else 0
)
avg_time = (
sum(r.time_seconds for r in all_rounds) / total_rounds
if total_rounds > 0
else 0
sum(r.distance_meters for r in all_rounds) / total_rounds if total_rounds > 0 else 0
)
avg_time = sum(r.time_seconds for r in all_rounds) / total_rounds if total_rounds > 0 else 0
# Find best and worst
scores = [g.total_score for g in games]
@ -106,9 +101,7 @@ class AnalysisService:
# Determine trend (simple moving average comparison)
trend = "stable"
if len(games) >= 4:
first_half = sum(g.total_score for g in games[: len(games) // 2]) / (
len(games) // 2
)
first_half = sum(g.total_score for g in games[: len(games) // 2]) / (len(games) // 2)
second_half = sum(g.total_score for g in games[len(games) // 2 :]) / (
len(games) - len(games) // 2
)
@ -124,18 +117,22 @@ class AnalysisService:
for game in games:
for round_guess in game.rounds:
if round_guess.score < 2000:
weak_areas.append({
"game": game.token,
"round": round_guess.round_number,
"score": round_guess.score,
"distance": round_guess.distance_meters,
})
weak_areas.append(
{
"game": game.token,
"round": round_guess.round_number,
"score": round_guess.score,
"distance": round_guess.distance_meters,
}
)
elif round_guess.score >= 4500:
strong_areas.append({
"game": game.token,
"round": round_guess.round_number,
"score": round_guess.score,
})
strong_areas.append(
{
"game": game.token,
"round": round_guess.round_number,
"score": round_guess.score,
}
)
return GameAnalysis(
games_analyzed=len(games),
@ -204,9 +201,7 @@ class AnalysisService:
# Get comprehensive profile
try:
results["profile"] = await self.profile_service.get_comprehensive_profile(
session_token
)
results["profile"] = await self.profile_service.get_comprehensive_profile(session_token)
except Exception as e:
results["errors"].append(f"Profile: {str(e)}")
@ -227,17 +222,13 @@ class AnalysisService:
# Analyze recent games
try:
results["recent_games_analysis"] = await self.analyze_recent_games(
5, session_token
)
results["recent_games_analysis"] = await self.analyze_recent_games(5, session_token)
except Exception as e:
results["errors"].append(f"Recent games: {str(e)}")
# Get explorer progress
try:
response = await self.client.get(
self._create_endpoint("/v3/explorer"), session_token
)
response = await self.client.get(self._create_endpoint("/v3/explorer"), session_token)
if response.is_success:
results["explorer"] = response.summarize()
except Exception as e:
@ -245,9 +236,7 @@ class AnalysisService:
# Get objectives
try:
response = await self.client.get(
self._create_endpoint("/v4/objectives"), session_token
)
response = await self.client.get(self._create_endpoint("/v4/objectives"), session_token)
if response.is_success:
results["objectives"] = response.summarize()
except Exception as e:
@ -273,42 +262,50 @@ class AnalysisService:
# Analyze perfect round rate
if analysis.perfect_round_percentage < 20:
recommendations.append({
"category": "accuracy",
"priority": "high",
"recommendation": "Focus on improving pinpoint accuracy",
"detail": f"Your perfect round rate is {analysis.perfect_round_percentage:.1f}%. "
"Practice with familiar maps to build confidence.",
})
recommendations.append(
{
"category": "accuracy",
"priority": "high",
"recommendation": "Focus on improving pinpoint accuracy",
"detail": f"Your perfect round rate is {analysis.perfect_round_percentage:.1f}%. "
"Practice with familiar maps to build confidence.",
}
)
# Analyze time usage
if analysis.average_time_seconds < 30:
recommendations.append({
"category": "time_management",
"priority": "medium",
"recommendation": "Consider taking more time per round",
"detail": f"Average time: {analysis.average_time_seconds:.0f}s. "
"Taking a bit more time can improve accuracy.",
})
recommendations.append(
{
"category": "time_management",
"priority": "medium",
"recommendation": "Consider taking more time per round",
"detail": f"Average time: {analysis.average_time_seconds:.0f}s. "
"Taking a bit more time can improve accuracy.",
}
)
# Analyze score trend
if analysis.score_trend == "declining":
recommendations.append({
"category": "consistency",
"priority": "high",
"recommendation": "Your scores are trending downward",
"detail": "Consider taking breaks and reviewing your weak areas.",
})
recommendations.append(
{
"category": "consistency",
"priority": "high",
"recommendation": "Your scores are trending downward",
"detail": "Consider taking breaks and reviewing your weak areas.",
}
)
# Check for weak areas pattern
if len(analysis.weak_areas) > 5:
recommendations.append({
"category": "practice",
"priority": "medium",
"recommendation": "Practice specific regions",
"detail": f"You had {len(analysis.weak_areas)} rounds under 2000 points. "
"Consider using region-specific practice maps.",
})
recommendations.append(
{
"category": "practice",
"priority": "medium",
"recommendation": "Practice specific regions",
"detail": f"You had {len(analysis.weak_areas)} rounds under 2000 points. "
"Consider using region-specific practice maps.",
}
)
return {
"analysis_summary": {
@ -331,4 +328,5 @@ class AnalysisService:
def _create_endpoint(path: str):
"""Create simple endpoint info for raw requests."""
from ..api.endpoints import EndpointInfo
return EndpointInfo(path=path, description=f"Request to {path}")

View file

@ -7,11 +7,11 @@ Handles game history, details, and competitive data with dynamic schema support.
import logging
from typing import Optional
from ..api.client import GeoGuessrClient, DynamicResponse
from ..api.client import DynamicResponse, GeoGuessrClient
from ..api.endpoints import Endpoints
from ..models.DailyChallenge import DailyChallenge
from ..models.Game import Game
from ..models.SeasonStats import SeasonStats
from ..models.DailyChallenge import DailyChallenge
logger = logging.getLogger(__name__)
@ -23,9 +23,9 @@ class GameService:
self.client = client
async def get_game_details(
self,
game_token: str,
session_token: Optional[str] = None,
self,
game_token: str,
session_token: Optional[str] = None,
) -> tuple[Game, DynamicResponse]:
"""
Get details for a specific game.
@ -47,26 +47,26 @@ class GameService:
raise ValueError(f"Failed to get game details: {response.data}")
async def get_unfinished_games(
self,
session_token: Optional[str] = None,
self,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""Get list of unfinished games."""
return await self.client.get(Endpoints.GAMES.GET_UNFINISHED_GAMES, session_token)
async def get_streak_game(
self,
game_token: str,
session_token: Optional[str] = None,
self,
game_token: str,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""Get streak game details."""
endpoint = Endpoints.GAMES.get_streak_game(game_token)
return await self.client.get(endpoint, session_token)
async def get_activity_feed(
self,
count: int = 10,
page: int = 0,
session_token: Optional[str] = None,
self,
count: int = 10,
page: int = 0,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""
Get the activity feed.
@ -83,9 +83,9 @@ class GameService:
return await self.client.get(endpoint, session_token)
async def get_recent_games(
self,
count: int = 10,
session_token: Optional[str] = None,
self,
count: int = 10,
session_token: Optional[str] = None,
) -> list[Game]:
"""
Get recent games from the activity feed.
@ -124,8 +124,8 @@ class GameService:
return games
async def get_season_stats(
self,
session_token: Optional[str] = None,
self,
session_token: Optional[str] = None,
) -> tuple[SeasonStats, DynamicResponse]:
"""Get active season statistics."""
response = await self.client.get(
@ -139,9 +139,9 @@ class GameService:
raise ValueError(f"Failed to get season stats: {response.data}")
async def get_daily_challenge(
self,
day: str = "today",
session_token: Optional[str] = None,
self,
day: str = "today",
session_token: Optional[str] = None,
) -> tuple[DailyChallenge, DynamicResponse]:
"""
Get daily challenge.
@ -163,26 +163,26 @@ class GameService:
raise ValueError(f"Failed to get daily challenge: {response.data}")
async def get_battle_royale(
self,
game_id: str,
session_token: Optional[str] = None,
self,
game_id: str,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""Get battle royale game details."""
endpoint = Endpoints.GAME_SERVER.get_battle_royale(game_id)
return await self.client.get(endpoint, session_token)
async def get_duel(
self,
duel_id: str,
session_token: Optional[str] = None,
self,
duel_id: str,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""Get duel game details."""
endpoint = Endpoints.GAME_SERVER.get_duel(duel_id)
return await self.client.get(endpoint, session_token)
async def get_tournaments(
self,
session_token: Optional[str] = None,
self,
session_token: Optional[str] = None,
) -> DynamicResponse:
"""Get tournament information."""
return await self.client.get(Endpoints.GAME_SERVER.GET_TOURNAMENTS, session_token)

View file

@ -8,7 +8,7 @@ dynamic schema adaptation.
import logging
from typing import Optional
from ..api.client import GeoGuessrClient, DynamicResponse
from ..api.client import DynamicResponse, GeoGuessrClient
from ..api.endpoints import Endpoints
from ..models.Achievement import Achievement
from ..models.UserProfile import UserProfile
@ -171,11 +171,7 @@ class ProfileService:
"unlocked": len(unlocked),
"recent": [
{"name": a.name, "unlocked_at": a.unlocked_at}
for a in sorted(
unlocked,
key=lambda x: x.unlocked_at or "",
reverse=True
)[:5]
for a in sorted(unlocked, key=lambda x: x.unlocked_at or "", reverse=True)[:5]
],
}
except Exception as e: