Added user activity score #451 #452
@ -31,6 +31,10 @@ class UserRepositoryABC(ABC):
|
||||
def get_users_by_server_id(self, server_id: int) -> List[User]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_users_with_activity_by_server_id(self, server_id: int) -> List[User]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
|
||||
pass
|
||||
|
@ -32,6 +32,8 @@ class User(TableABC):
|
||||
self._birthday = birthday
|
||||
self._server = server
|
||||
|
||||
self._activity = 0
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
@ -120,6 +122,14 @@ class User(TableABC):
|
||||
return 0
|
||||
return float(result)
|
||||
|
||||
@property
|
||||
def activity(self) -> int:
|
||||
return self._activity
|
||||
|
||||
@activity.setter
|
||||
def activity(self, value: int):
|
||||
self._activity = value
|
||||
|
||||
@property
|
||||
@ServiceProviderABC.inject
|
||||
def level(self, services: ServiceProviderABC) -> Level:
|
||||
|
@ -1,6 +1,8 @@
|
||||
import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.type import T, R
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
@ -38,7 +40,9 @@ class UserRepositoryService(UserRepositoryABC):
|
||||
|
||||
def get_users(self) -> List[User]:
|
||||
self._logger.trace(__name__, f"Send SQL command: {User.get_select_all_string()}")
|
||||
return List(User, [self._from_result(user) for user in self._context.select(User.get_select_all_string())])
|
||||
return List(
|
||||
User, [self._from_result(user) for user in self._context.select(User.get_select_all_string())]
|
||||
).for_each(lambda x: self._set_user_activity(x))
|
||||
|
||||
def get_user_by_id(self, id: int) -> User:
|
||||
self._logger.trace(__name__, f"Send SQL command: {User.get_select_by_id_string(id)}")
|
||||
@ -77,6 +81,16 @@ class UserRepositoryService(UserRepositoryABC):
|
||||
[self._from_result(user) for user in self._context.select(User.get_select_by_server_id_string(server_id))],
|
||||
)
|
||||
|
||||
def get_users_with_activity_by_server_id(self, server_id: int) -> List[User]:
|
||||
self._logger.trace(
|
||||
__name__,
|
||||
f"Send SQL command: {User.get_select_by_server_id_string(server_id)}",
|
||||
)
|
||||
return List(
|
||||
User,
|
||||
[self._from_result(user) for user in self._context.select(User.get_select_by_server_id_string(server_id))],
|
||||
).for_each(lambda x: self._set_user_activity(x))
|
||||
|
||||
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
|
||||
self._logger.trace(
|
||||
__name__,
|
||||
@ -109,3 +123,91 @@ class UserRepositoryService(UserRepositoryABC):
|
||||
def delete_user(self, user: User):
|
||||
self._logger.trace(__name__, f"Send SQL command: {user.delete_string}")
|
||||
self._context.cursor.execute(user.delete_string)
|
||||
|
||||
def _set_user_activity(self, user):
|
||||
days = (datetime.date.today() - (datetime.date.today() - datetime.timedelta(days=7))).days
|
||||
query = f"""
|
||||
SELECT (
|
||||
(
|
||||
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 = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserGotAchievements.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) +
|
||||
(
|
||||
SELECT SUM(
|
||||
UserMessageCountPerHour.XPCount / (
|
||||
SELECT XpPerMessage
|
||||
FROM CFG_Server
|
||||
WHERE ServerId = {user.server.id}
|
||||
)
|
||||
)
|
||||
FROM UserMessageCountPerHour
|
||||
INNER JOIN Users ON UserMessageCountPerHour.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserMessageCountPerHour.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) +
|
||||
(
|
||||
SELECT Count(UserJoinedVoiceChannel.CreatedAt)
|
||||
FROM UserJoinedVoiceChannel
|
||||
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserJoinedVoiceChannel.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) +
|
||||
(
|
||||
SELECT IFNULL(ROUND(SUM(TIME_TO_SEC(
|
||||
TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)
|
||||
) / 3600), 2), 0)
|
||||
FROM UserJoinedVoiceChannel
|
||||
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserJoinedVoiceChannel.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) +
|
||||
(
|
||||
SELECT Count(UserJoinedGameServer.CreatedAt)
|
||||
FROM UserJoinedGameServer
|
||||
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserJoinedGameServer.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) +
|
||||
(
|
||||
SELECT IFNULL(ROUND(SUM(TIME_TO_SEC(
|
||||
TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)
|
||||
) / 3600), 2), 0)
|
||||
FROM UserJoinedGameServer
|
||||
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserJoinedGameServer.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
) -
|
||||
(
|
||||
SELECT COUNT(UserWarnings.CreatedAt)
|
||||
FROM UserWarnings
|
||||
INNER JOIN Users ON UserWarnings.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {user.server.id}
|
||||
AND Users.UserId = {user.id}
|
||||
AND UserWarnings.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
|
||||
)
|
||||
) / {days} * 1000 as count;
|
||||
"""
|
||||
user.activity = self._cast_query_result(query, int)
|
||||
|
||||
def _cast_query_result(self, query: str, r_type: T) -> Optional[R]:
|
||||
results = self._context.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
|
||||
|
@ -64,11 +64,9 @@ class QueryABC(ObjectType):
|
||||
if user == "system" or user.auth_role == AuthRoleEnum.admin:
|
||||
return self._resolve_collection(collection, *args, **kwargs)
|
||||
|
||||
for x in collection.to_list():
|
||||
if not self._can_user_see_element(user, x):
|
||||
collection.remove(x)
|
||||
|
||||
return self._resolve_collection(collection, *args, **kwargs)
|
||||
return self._resolve_collection(
|
||||
collection.where(lambda x: self._can_user_see_element(user, x)), *args, **kwargs
|
||||
)
|
||||
|
||||
self.set_field(f"{name}s", wrapper)
|
||||
self.set_field(f"{name}Count", lambda *args: wrapper(*args).count())
|
||||
|
@ -9,6 +9,7 @@ type User implements TableWithHistoryQuery {
|
||||
ontime: Float
|
||||
gameOntime: Float
|
||||
level: Level
|
||||
activityScore: Int
|
||||
|
||||
joinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer]
|
||||
joinedServerCount: Int
|
||||
|
@ -86,7 +86,7 @@ class ServerQuery(DataQueryWithHistoryABC):
|
||||
)
|
||||
self.add_collection(
|
||||
"user",
|
||||
lambda server, *_: self._users.get_users_by_server_id(server.id),
|
||||
lambda server, *_: self._users.get_users_with_activity_by_server_id(server.id),
|
||||
UserFilter,
|
||||
)
|
||||
self.add_collection(
|
||||
|
@ -114,7 +114,9 @@ class ServerStatisticQuery(QueryABC):
|
||||
|
||||
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
|
||||
SELECT IFNULL(ROUND(SUM(
|
||||
TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600
|
||||
), 2), 0) FROM UserJoinedVoiceChannel
|
||||
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {server.server.id}
|
||||
AND UserJoinedVoiceChannel.CreatedAt >= "{self._get_date(**server.kwargs)}";
|
||||
@ -132,7 +134,10 @@ class ServerStatisticQuery(QueryABC):
|
||||
|
||||
def _resolve_game_server_ontime(self, server, *_):
|
||||
query = f"""
|
||||
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600),2) FROM UserJoinedGameServer
|
||||
SELECT IFNULL(ROUND(SUM(
|
||||
TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600
|
||||
), 2), 0)
|
||||
FROM UserJoinedGameServer
|
||||
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
|
||||
WHERE Users.ServerId = {server.server.id}
|
||||
AND UserJoinedGameServer.CreatedAt >= "{self._get_date(**server.kwargs)}";
|
||||
|
@ -59,6 +59,7 @@ class UserQuery(DataQueryWithHistoryABC):
|
||||
self.set_field("ontime", lambda user, *_: user.ontime)
|
||||
self.set_field("gameOntime", lambda user, *_: user.game_ontime)
|
||||
self.set_field("level", lambda user, *_: user.level)
|
||||
self.set_field("activityScore", lambda user, *_: user.activity)
|
||||
self.add_collection(
|
||||
"joinedServer",
|
||||
lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.id),
|
||||
|
@ -18,6 +18,7 @@ export interface User extends DataWithHistory {
|
||||
ontime?: number;
|
||||
gameOntime?: number;
|
||||
level?: Level;
|
||||
activityScore?: number;
|
||||
server?: Server;
|
||||
leftServer?: boolean;
|
||||
|
||||
|
@ -362,6 +362,7 @@ export class Queries {
|
||||
xp
|
||||
ontime
|
||||
gameOntime
|
||||
activityScore
|
||||
level {
|
||||
id
|
||||
name
|
||||
@ -388,6 +389,7 @@ export class Queries {
|
||||
birthday
|
||||
ontime
|
||||
gameOntime
|
||||
activityScore
|
||||
level {
|
||||
id
|
||||
name
|
||||
|
@ -74,6 +74,13 @@
|
||||
</div>
|
||||
</th>
|
||||
|
||||
<th hideable-th="activity" [parent]="this" [sortable]="true">
|
||||
<div class="table-header-label">
|
||||
<div class="table-header-text">{{'common.activity' | translate}}</div>
|
||||
<p-sortIcon field="activityScore" class="table-header-icon"></p-sortIcon>
|
||||
</div>
|
||||
</th>
|
||||
|
||||
<th hideable-th="left_server" [parent]="this" [sortable]="true">
|
||||
<div class="table-header-label">
|
||||
<div class="table-header-text">{{'common.left_server' | translate}}</div>
|
||||
@ -127,6 +134,7 @@
|
||||
<th hideable-th="xp" [parent]="this"></th>
|
||||
<th hideable-th="ontime" [parent]="this"></th>
|
||||
<th hideable-th="game_ontime" [parent]="this"></th>
|
||||
<th hideable-th="activity" [parent]="this"></th>
|
||||
<th hideable-th="left_server" [parent]="this" class="table-header-small-dropdown">
|
||||
<form [formGroup]="filterForm">
|
||||
<p-dropdown formControlName="leftServer" [options]="leftServerOptions"
|
||||
@ -213,6 +221,17 @@
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
<td hideable-th="activity" [parent]="this">
|
||||
<span class="p-column-title">{{'common.activity' | translate}}:</span>
|
||||
<p-cellEditor>
|
||||
<ng-template pTemplate="input">
|
||||
{{member.activityScore}}
|
||||
</ng-template>
|
||||
<ng-template pTemplate="output">
|
||||
{{member.activityScore}}
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
<td hideable-th="left_server" [parent]="this">
|
||||
<span class="p-column-title">{{'common.left_server' | translate}}:</span>
|
||||
<p-cellEditor>
|
||||
|
@ -89,7 +89,7 @@ export class MembersComponent extends ComponentWithTable implements OnInit, OnDe
|
||||
private data: DataService,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
super("member", ["id", "discord_id", "name", "xp", "ontime", "game_ontime", "left_server", "level"]);
|
||||
super("member", ["id", "discord_id", "name", "xp", "ontime", "game_ontime", "activity", "left_server", "level"]);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -75,6 +75,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'common.activity' | translate}}:</div>
|
||||
<div class="content-data-value">{{user.activityScore}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'view.server.profile.level' | translate}}:</div>
|
||||
|
@ -127,6 +127,7 @@
|
||||
"abort": "Abbrechen",
|
||||
"actions": "Aktionen",
|
||||
"active": "Aktiv",
|
||||
"activity": "Aktivität",
|
||||
"add": "Hinzufügen",
|
||||
"attribute": "Attribut",
|
||||
"auth_role": "Rolle",
|
||||
|
@ -127,6 +127,7 @@
|
||||
"abort": "Abort",
|
||||
"actions": "Actions",
|
||||
"active": "Active",
|
||||
"activity": "Activity",
|
||||
"add": "Add",
|
||||
"attribute": "Attribute",
|
||||
"auth_role": "Role",
|
||||
|
Loading…
Reference in New Issue
Block a user