(stats): New xp display format.

This commit is contained in:
2023-10-09 16:50:35 +03:00
parent 50a1a9c8a1
commit d674dc4c8e
3 changed files with 77 additions and 10 deletions

Submodule src/gui updated: 24e94d10e2...f2760218ef

View File

@@ -6,11 +6,28 @@ import discord
from meta import LionBot from meta import LionBot
from gui.cards import StatsCard from gui.cards import StatsCard
from gui.base import CardMode from gui.base import CardMode
from tracking.text.data import TextTrackerData
from .. import babel
from ..data import StatsData from ..data import StatsData
_p = babel._p
def format_time(seconds):
return "{:02}:{:02}".format(
int(seconds // 3600),
int(seconds % 3600 // 60)
)
def format_xp(messages, xp):
return f"{messages} ({xp} XP)"
async def get_stats_card(bot: LionBot, userid: int, guildid: int, mode: CardMode): async def get_stats_card(bot: LionBot, userid: int, guildid: int, mode: CardMode):
t = bot.translator.t
data: StatsData = bot.get_cog('StatsCog').data data: StatsData = bot.get_cog('StatsCog').data
# TODO: Workouts # TODO: Workouts
@@ -32,28 +49,41 @@ async def get_stats_card(bot: LionBot, userid: int, guildid: int, mode: CardMode
) )
# Extract the study times for each period # Extract the study times for each period
if mode in (CardMode.STUDY, CardMode.VOICE): if mode in (CardMode.STUDY, CardMode.VOICE, CardMode.ANKI):
model = data.VoiceSessionStats model = data.VoiceSessionStats
refkey = (guildid or None, userid) refkey = (guildid or None, userid)
ref_since = model.study_times_since ref_since = model.study_times_since
ref_between = model.study_times_between ref_between = model.study_times_between
period_activity = await ref_since(*refkey, *period_timestamps)
period_strings = [format_time(activity) for activity in reversed(period_activity)]
month_activity = period_activity[1]
month_string = t(_p(
'gui:stats|mode:voice|month',
"{hours} hours"
)).format(hours=int(month_activity // 3600))
elif mode is CardMode.TEXT: elif mode is CardMode.TEXT:
msgmodel = TextTrackerData.TextSessions
if guildid: if guildid:
model = data.MemberExp model = data.MemberExp
msg_since = msgmodel.member_messages_since
refkey = (guildid, userid) refkey = (guildid, userid)
else: else:
model = data.UserExp model = data.UserExp
msg_since = msgmodel.member_messages_between
refkey = (userid,) refkey = (userid,)
ref_since = model.xp_since ref_since = model.xp_since
ref_between = model.xp_between ref_between = model.xp_between
else:
# TODO ANKI
model = data.VoiceSessionStats
refkey = (guildid, userid)
ref_since = model.study_times_since
ref_between = model.study_times_between
study_times = await ref_since(*refkey, *period_timestamps) xp_period_activity = await ref_since(*refkey, *period_timestamps)
msg_period_activity = await msg_since(*refkey, *period_timestamps)
period_strings = [
format_xp(msgs, xp)
for msgs, xp in zip(reversed(msg_period_activity), reversed(xp_period_activity))
]
month_string = f"{xp_period_activity[1]} XP"
else:
raise ValueError(f"Mode {mode} not supported")
# Get leaderboard position # Get leaderboard position
# TODO: Efficiency # TODO: Efficiency
@@ -89,7 +119,8 @@ async def get_stats_card(bot: LionBot, userid: int, guildid: int, mode: CardMode
card = StatsCard( card = StatsCard(
(position, 0), (position, 0),
list(reversed(study_times)), period_strings,
month_string,
100, 100,
streaks, streaks,
skin={'mode': mode} skin={'mode': mode}

View File

@@ -288,6 +288,42 @@ class TextTrackerData(Registry):
tuple(chain((userid, guildid), points)) tuple(chain((userid, guildid), points))
) )
return [r['messages'] or 0 for r in await cursor.fetchall()] return [r['messages'] or 0 for r in await cursor.fetchall()]
@classmethod
@log_wrap(action='user_messages_since')
async def user_messages_since(cls, userid: int, *points):
"""
Compute messages written between the given points.
"""
query = sql.SQL(
"""
SELECT
(
SELECT
SUM(messages)
FROM text_sessions s
WHERE
s.userid = %s
AND s.start_time >= t._start
) AS messages
FROM
(VALUES {})
AS
t (_start)
ORDER BY t._start
"""
).format(
sql.SQL(', ').join(
sql.SQL("({})").format(sql.Placeholder()) for _ in points
)
)
async with cls._connector.connection() as conn:
async with conn.cursor() as cursor:
await cursor.execute(
query,
tuple(chain((userid,), points))
)
return [r['messages'] or 0 for r in await cursor.fetchall()]
@classmethod @classmethod
@log_wrap(action='msgs_leaderboard_all') @log_wrap(action='msgs_leaderboard_all')