Improved generic achievement logic #268_achievements

This commit is contained in:
Sven Heidemann 2023-07-15 13:38:10 +02:00
parent 2293849d94
commit 3fb951a748
2 changed files with 64 additions and 15 deletions

View File

@ -0,0 +1,43 @@
from typing import List
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.model.user import User
class AchievementAttributeResolver:
def __init__(
self,
auto_roles: AutoRoleRepositoryABC,
clients: ClientRepositoryABC,
known_users: KnownUserRepositoryABC,
levels: LevelRepositoryABC,
servers: ServerRepositoryABC,
user_joined_servers: UserJoinedServerRepositoryABC,
user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC,
user_joined_game_server: UserJoinedGameServerRepositoryABC,
users: UserRepositoryABC,
achievements: AchievementRepositoryABC,
):
self._auto_roles = auto_roles
self._clients = clients
self._known_users = known_users
self._levels = levels
self._servers = servers
self._user_joined_servers = user_joined_servers
self._user_joined_voice_channels = user_joined_voice_channels
self._user_joined_game_server = user_joined_game_server
self._users = users
self._achievements = achievements
def get_played_on_game_server(self, user: User) -> List[str]:
joins = self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id)
return joins.select(lambda x: x.name)

View File

@ -11,6 +11,7 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
from bot_data.model.achievement import Achievement from bot_data.model.achievement import Achievement
from bot_data.model.user import User from bot_data.model.user import User
from bot_data.model.user_got_achievement import UserGotAchievement from bot_data.model.user_got_achievement import UserGotAchievement
from modules.achievements.achievement_attribute_resolver import AchievementAttributeResolver
from modules.achievements.model.achievement_attribute import AchievementAttribute from modules.achievements.model.achievement_attribute import AchievementAttribute
@ -23,6 +24,7 @@ class AchievementService:
achievements: AchievementRepositoryABC, achievements: AchievementRepositoryABC,
db: DatabaseContextABC, db: DatabaseContextABC,
message_service: MessageService, message_service: MessageService,
resolver: AchievementAttributeResolver,
t: TranslatePipe, t: TranslatePipe,
): ):
self._config = config self._config = config
@ -42,28 +44,32 @@ class AchievementService:
AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number"), AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number"),
AchievementAttribute("ontime", lambda user: user.ontime, "number"), AchievementAttribute("ontime", lambda user: user.ontime, "number"),
AchievementAttribute("level", lambda user: user.level, "Level"), AchievementAttribute("level", lambda user: user.level, "Level"),
# special cases
AchievementAttribute(
"played_on_game_server", lambda user: resolver.get_played_on_game_server(user), "GameServer"
),
AchievementAttribute("last_single_ontime_hours", lambda user: user.level, "GameServer"),
] ]
) )
self._operators = {
"==": lambda value, expected_value: value == expected_value,
"!=": lambda value, expected_value: value != expected_value,
"<=": lambda value, expected_value: value <= expected_value,
">=": lambda value, expected_value: value >= expected_value,
"<": lambda value, expected_value: value < expected_value,
">": lambda value, expected_value: value > expected_value,
"contains": lambda value, expected_value: expected_value in value,
}
def get_operators(self) -> list[str]:
return [x for x in self._operators.keys()]
def get_attributes(self) -> List[AchievementAttribute]: def get_attributes(self) -> List[AchievementAttribute]:
return self._attributes return self._attributes
def _match(self, value: str, operator: str, expected_value: str) -> bool: def _match(self, value: str, operator: str, expected_value: str) -> bool:
match operator: return self._operators[operator](value, expected_value)
case "==":
return value == expected_value
case "!=":
return value != expected_value
case "<=":
return value <= expected_value
case ">=":
return value >= expected_value
case "<":
return value < expected_value
case ">":
return value > expected_value
case _:
raise ValueError(f"Invalid operator: ${operator}")
def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool: def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool:
user_achievements = self._achievements.get_achievements_by_user_id(user.id) user_achievements = self._achievements.get_achievements_by_user_id(user.id)