diff --git a/bot/src/bot_graphql/graphql/server.gql b/bot/src/bot_graphql/graphql/server.gql index 9849f6ab..be603f3a 100644 --- a/bot/src/bot_graphql/graphql/server.gql +++ b/bot/src/bot_graphql/graphql/server.gql @@ -38,7 +38,7 @@ type Server implements TableWithHistoryQuery { config: ServerConfig hasFeatureFlag(flag: String): FeatureFlag -# statistic(date: String): ServerStatistic + statistic(date: String): ServerStatistic createdAt: String modifiedAt: String diff --git a/bot/src/bot_graphql/queries/server_query.py b/bot/src/bot_graphql/queries/server_query.py index 6f2abb1c..14033101 100644 --- a/bot/src/bot_graphql/queries/server_query.py +++ b/bot/src/bot_graphql/queries/server_query.py @@ -108,7 +108,7 @@ class ServerQuery(DataQueryWithHistoryABC): "hasFeatureFlag", lambda server, *_, **kwargs: self._resolve_has_feature_flag(server, *_, **kwargs), ) - # self.set_field("statistic", lambda server, *_, **kwargs: ServerStatistics(server, kwargs)) + self.set_field("statistic", lambda server, *_, **kwargs: ServerStatistics(server, kwargs)) @staticmethod def resolve_id(server: Server, *_): diff --git a/bot/src/bot_graphql/queries/server_statistic_query.py b/bot/src/bot_graphql/queries/server_statistic_query.py index 7fa4d9c1..661d8142 100644 --- a/bot/src/bot_graphql/queries/server_statistic_query.py +++ b/bot/src/bot_graphql/queries/server_statistic_query.py @@ -1,6 +1,9 @@ import datetime +from typing import Optional from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_core.type import R, T from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC @@ -8,7 +11,6 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoic from bot_data.abc.user_message_count_per_hour_repository_abc import UserMessageCountPerHourRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC -from bot_data.model.server_config import ServerConfig from bot_graphql.abc.query_abc import QueryABC @@ -22,10 +24,13 @@ class ServerStatisticQuery(QueryABC): user_messages: UserMessageCountPerHourRepositoryABC, user_warnings: UserWarningsRepositoryABC, achievements: AchievementRepositoryABC, + db: DatabaseContextABC, ): QueryABC.__init__(self, "ServerStatistic") self._config = config + self._db = db + self._users = users self._user_joined_voice_channels = user_joined_voice_channels self._user_joined_game_servers = user_joined_game_servers @@ -44,7 +49,7 @@ class ServerStatisticQuery(QueryABC): ) self.set_field("userCount", lambda server, *_: self._users.get_users_by_server_id(server.server.id).count()) - self.set_field("activeUserCount", self._resolve_active_count) + self.set_field("activeUserCount", self._resolve_active_user_count) self.set_field("userJoinedVoiceChannelCount", self._resolve_voice_channel_count) self.set_field("userJoinedVoiceChannelOntime", self._resolve_voice_channel_ontime) @@ -56,6 +61,93 @@ class ServerStatisticQuery(QueryABC): self.set_field("activityScore", self._resolve_activity_score) + def _resolve_active_user_count(self, server, *_): + return self._users.get_users_by_server_id(server.server.id).where(lambda x: not x.left_server).count() + + def _cast_query_result(self, query: str, r_type: T) -> Optional[R]: + results = self._db.select(query) + if len(results) == 0 or len(results[0]) == 0: + return None + result = results[0][0] + default = None + if r_type is int or r_type is float: + default = 0 + elif r_type is str: + default = "" + + return r_type(result) if result is not None else default + + def _resolve_achievements(self, server, *_): + query = f""" + SELECT Count(UserGotAchievements.CreatedAt) FROM UserGotAchievements + INNER JOIN Achievements ON UserGotAchievements.AchievementId = Achievements.Id + INNER JOIN Users ON UserGotAchievements.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserGotAchievements.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, int) + + def _resolve_message_count(self, server, *_): + query = f""" + SELECT SUM( + UserMessageCountPerHour.XPCount / ( + SELECT XpPerMessage + FROM CFG_Server + WHERE ServerId = {server.server.id} + ) + ) + FROM UserMessageCountPerHour + INNER JOIN Users ON UserMessageCountPerHour.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserMessageCountPerHour.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, int) + + def _resolve_voice_channel_count(self, server, *_): + query = f""" + SELECT Count(UserJoinedVoiceChannel.CreatedAt) FROM UserJoinedVoiceChannel + INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserJoinedVoiceChannel.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, int) + + def _resolve_voice_channel_ontime(self, server, *_): + query = f""" + SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600),{server.server.id}) FROM UserJoinedVoiceChannel + INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserJoinedVoiceChannel.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, float) + + def _resolve_game_server_count(self, server, *_): + query = f""" + SELECT Count(UserJoinedGameServer.CreatedAt) FROM UserJoinedGameServer + INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserJoinedGameServer.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, int) + + def _resolve_game_server_ontime(self, server, *_): + query = f""" + SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600),{server.server.id}) FROM UserJoinedGameServer + INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserJoinedGameServer.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, float) + + def _resolve_user_warning_count(self, server, *_): + query = f""" + SELECT COUNT(UserWarnings.CreatedAt) FROM UserWarnings + INNER JOIN Users ON UserWarnings.UserId = Users.UserId + WHERE Users.ServerId = {server.server.id} + AND UserWarnings.CreatedAt >= "{self._get_date(**server.kwargs)}"; + """ + return self._cast_query_result(query, int) + def _resolve_activity_score(self, server, *_): days = (datetime.date.today() - self._get_date(**server.kwargs)).days return int( @@ -69,87 +161,12 @@ class ServerStatisticQuery(QueryABC): + self._resolve_game_server_ontime(server, *_) - self._resolve_user_warning_count(server, *_) ) - / self._resolve_active_count(server, *_) + / self._resolve_active_user_count(server, *_) ) / days * 1000 ) - def _resolve_message_count(self, server, *_): - settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{server.server.discord_id}") - return ( - self._user_messages.get_user_message_count_per_hours() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .sum(lambda x: x.xp_count / settings.xp_per_message) - ) - - def _resolve_active_count(self, server, *_): - return self._users.get_users_by_server_id(server.server.id).where(lambda x: not x.left_server).count() - - def _resolve_voice_channel_count(self, server, *_): - return ( - self._user_joined_voice_channels.get_user_joined_voice_channels() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .count() - ) - - def _resolve_voice_channel_ontime(self, server, *_): - return ( - self._user_joined_voice_channels.get_user_joined_voice_channels() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .sum(lambda x: x.time) - ) - - def _resolve_game_server_count(self, server, *_): - return ( - self._user_joined_game_servers.get_user_joined_game_servers() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .count() - ) - - def _resolve_game_server_ontime(self, server, *_): - return ( - self._user_joined_game_servers.get_user_joined_game_servers() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .sum(lambda x: x.time) - ) - - def _resolve_user_warning_count(self, server, *_): - return ( - self._user_warnings.get_user_warnings() - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .count() - ) - - def _resolve_achievements(self, server, *_): - return ( - self._achievements.get_achievements_by_server_id(server.server.id) - .select_many(lambda x: self._achievements.get_user_got_achievements_by_achievement_id(x.id)) - .where( - lambda x: x.user.server.id == server.server.id - and x.created_at.date() >= self._get_date(**server.kwargs) - ) - .count() - ) - def _get_date(self, **kwargs) -> datetime.date: if "date" not in kwargs: return datetime.date.today() - datetime.timedelta(days=7) diff --git a/web/src/app/models/graphql/queries.model.ts b/web/src/app/models/graphql/queries.model.ts index 0b4c97cb..09e582d5 100644 --- a/web/src/app/models/graphql/queries.model.ts +++ b/web/src/app/models/graphql/queries.model.ts @@ -92,23 +92,22 @@ export class Queries { receivedCommandCount movedUsersCount } + statistic { + achievementsAchieved + messageCount + userCount + activeUserCount + userJoinedVoiceChannelCount + userJoinedVoiceChannelOntime + userJoinedGameServerCount + userJoinedGameServerOntime + userWarningCount + activityScore + } } } `; - // statistic { - // achievementsAchieved - // messageCount - // userCount - // activeUserCount - // userJoinedVoiceChannelCount - // userJoinedVoiceChannelOntime - // userJoinedGameServerCount - // userJoinedGameServerOntime - // userWarningCount - // activityScore - // } - static hasServerFeatureFlag = ` query HasServerFeatureFlag($filter: ServerFilter, $flag: String) { servers(filter: $filter) {