mirror of https://github.com/stijndcl/didier
Add stats for cf
parent
de7b5cd960
commit
a051423203
|
@ -0,0 +1,76 @@
|
|||
"""Currency updates
|
||||
|
||||
Revision ID: 8f7e8384cec3
|
||||
Revises: 09128b6e34dd
|
||||
Create Date: 2024-03-03 17:48:36.205106
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "8f7e8384cec3"
|
||||
down_revision = "09128b6e34dd"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table(
|
||||
"cf_stats",
|
||||
sa.Column("cf_stats_id", sa.Integer(), nullable=False),
|
||||
sa.Column("games_won", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.Column("games_lost", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.Column("dinks_won", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.Column("dinks_lost", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user_id"],
|
||||
["users.user_id"],
|
||||
),
|
||||
sa.PrimaryKeyConstraint("cf_stats_id"),
|
||||
)
|
||||
op.create_table(
|
||||
"jail",
|
||||
sa.Column("jail_entry_i", sa.Integer(), nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("until", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user_id"],
|
||||
["users.user_id"],
|
||||
),
|
||||
sa.PrimaryKeyConstraint("jail_entry_i"),
|
||||
)
|
||||
op.create_table(
|
||||
"savings",
|
||||
sa.Column("savings_id", sa.Integer(), nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("saved", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.Column("daily_minimum", sa.BigInteger(), server_default="0", nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user_id"],
|
||||
["users.user_id"],
|
||||
),
|
||||
sa.PrimaryKeyConstraint("savings_id"),
|
||||
)
|
||||
with op.batch_alter_table("bank", schema=None) as batch_op:
|
||||
batch_op.drop_column("invested")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("bank", schema=None) as batch_op:
|
||||
batch_op.add_column(
|
||||
sa.Column(
|
||||
"invested", sa.BIGINT(), server_default=sa.text("'0'::bigint"), autoincrement=False, nullable=False
|
||||
)
|
||||
)
|
||||
|
||||
op.drop_table("savings")
|
||||
op.drop_table("jail")
|
||||
op.drop_table("cf_stats")
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,34 @@
|
|||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from database.schemas import CFStats
|
||||
|
||||
__all__ = ["get_cf_stats", "update_cf_stats"]
|
||||
|
||||
|
||||
async def get_cf_stats(session: AsyncSession, user_id: int) -> CFStats:
|
||||
"""Get a user's coinflip stats"""
|
||||
statement = select(CFStats).where(CFStats.user_id == user_id)
|
||||
result = (await session.execute(statement)).scalar_one_or_none()
|
||||
|
||||
if result is None:
|
||||
result = CFStats(user_id=user_id)
|
||||
session.add(result)
|
||||
await session.commit()
|
||||
await session.refresh(result)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
async def update_cf_stats(session: AsyncSession, user_id: int, outcome: int):
|
||||
"""Update a user's coinflip stats"""
|
||||
stats = await get_cf_stats(session, user_id)
|
||||
if outcome < 0:
|
||||
stats.games_lost += 1
|
||||
stats.dinks_lost += abs(outcome)
|
||||
else:
|
||||
stats.games_won += 1
|
||||
stats.dinks_won += outcome
|
||||
|
||||
session.add(stats)
|
||||
await session.commit()
|
|
@ -15,6 +15,7 @@ __all__ = [
|
|||
"BankSavings",
|
||||
"Birthday",
|
||||
"Bookmark",
|
||||
"CFStats",
|
||||
"CommandStats",
|
||||
"CustomCommand",
|
||||
"CustomCommandAlias",
|
||||
|
@ -106,6 +107,21 @@ class Bookmark(Base):
|
|||
user: Mapped[User] = relationship(back_populates="bookmarks", uselist=False, lazy="selectin")
|
||||
|
||||
|
||||
class CFStats(Base):
|
||||
"""A user's coinflipping stats"""
|
||||
|
||||
__tablename__ = "cf_stats"
|
||||
|
||||
cf_stats_id: Mapped[int] = mapped_column(primary_key=True)
|
||||
games_won: Mapped[int] = mapped_column(BigInteger, server_default="0", nullable=False)
|
||||
games_lost: Mapped[int] = mapped_column(BigInteger, server_default="0", nullable=False)
|
||||
dinks_won: Mapped[int] = mapped_column(BigInteger, server_default="0", nullable=False)
|
||||
dinks_lost: Mapped[int] = mapped_column(BigInteger, server_default="0", nullable=False)
|
||||
user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.user_id"))
|
||||
|
||||
user: Mapped[User] = relationship(back_populates="cf_stats", uselist=False, lazy="selectin")
|
||||
|
||||
|
||||
class CommandStats(Base):
|
||||
"""Metrics on how often commands are used"""
|
||||
|
||||
|
@ -349,6 +365,9 @@ class User(Base):
|
|||
bookmarks: Mapped[List[Bookmark]] = relationship(
|
||||
back_populates="user", uselist=True, lazy="selectin", cascade="all, delete-orphan"
|
||||
)
|
||||
cf_stats: Mapped[CFStats] = relationship(
|
||||
back_populates="user", uselist=True, lazy="selectin", cascade="all, delete-orphan"
|
||||
)
|
||||
command_stats: Mapped[List[CommandStats]] = relationship(
|
||||
back_populates="user", uselist=True, lazy="selectin", cascade="all, delete-orphan"
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ from typing import Annotated, Optional, Union
|
|||
|
||||
from discord.ext import commands
|
||||
|
||||
from database.crud.cf_stats import update_cf_stats
|
||||
from database.crud.currency import gamble_dinks
|
||||
from didier import Didier
|
||||
from didier.utils.discord.converters import abbreviated_number
|
||||
|
@ -17,6 +18,7 @@ class Gambling(commands.Cog):
|
|||
def __init__(self, client: Didier):
|
||||
self.client = client
|
||||
|
||||
@commands.max_concurrency(1, commands.BucketType.user, wait=True)
|
||||
@commands.command(name="coinflip", aliases=["cf", "flip"]) # type: ignore[arg-type]
|
||||
async def coinflip(
|
||||
self,
|
||||
|
@ -57,8 +59,11 @@ class Gambling(commands.Cog):
|
|||
async with self.client.postgres_session as session:
|
||||
received = await gamble_dinks(session, ctx.author.id, amount, 2, won)
|
||||
|
||||
if received == 0:
|
||||
return await ctx.reply("You don't have any Didier Dinks to wager.", mention_author=False)
|
||||
if received == 0:
|
||||
return await ctx.reply("You don't have any Didier Dinks to wager.", mention_author=False)
|
||||
|
||||
sign = 1 if won else -1
|
||||
await update_cf_stats(session, ctx.author.id, received * sign)
|
||||
|
||||
plural = pluralize("Didier Dink", received)
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from didier import Didier
|
||||
|
||||
|
||||
class Leaderboards(commands.Cog):
|
||||
"""Cog for various leaderboards"""
|
||||
|
||||
client: Didier
|
||||
|
||||
def __init__(self, client: Didier):
|
||||
self.client = client
|
||||
|
||||
@commands.hybrid_group(name="leaderboard", aliases=["lb"], invoke_without_command=True)
|
||||
async def leaderboard(self, ctx: commands.Context):
|
||||
"""List the top X for a given category"""
|
||||
# TODO
|
||||
|
||||
@leaderboard.command(name="dinks", aliases=["d"])
|
||||
async def dinks(self, ctx: commands.Context):
|
||||
"""See the users with the most Didier Dinks"""
|
||||
# TODO
|
||||
|
||||
|
||||
async def setup(client: Didier):
|
||||
"""Load the cog"""
|
||||
await client.add_cog(Leaderboards(client))
|
|
@ -0,0 +1,54 @@
|
|||
from typing import Optional
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from database.crud.cf_stats import get_cf_stats
|
||||
from didier import Didier
|
||||
|
||||
|
||||
class Stats(commands.Cog):
|
||||
"""Cog for various stats that Didier tracks"""
|
||||
|
||||
client: Didier
|
||||
|
||||
def __init__(self, client: Didier):
|
||||
self.client = client
|
||||
|
||||
@commands.hybrid_group(name="stats", invoke_without_command=True)
|
||||
async def stats(self, ctx: commands.Context):
|
||||
"""See stats about yourself or another user"""
|
||||
|
||||
@stats.command(name="cf", aliases=["coinflip"])
|
||||
async def _cf_stats(self, ctx: commands.Context, user: Optional[discord.User] = None):
|
||||
"""See a user's `Didier CF` stats"""
|
||||
async with ctx.typing(), self.client.postgres_session as session:
|
||||
user = user or ctx.author
|
||||
cf_stats = await get_cf_stats(session, user.id)
|
||||
|
||||
embed = discord.Embed(title="Didier CF Stats", colour=discord.Colour.blue())
|
||||
embed.set_author(name=user.display_name)
|
||||
|
||||
if user.avatar is not None:
|
||||
embed.set_thumbnail(url=user.avatar.url)
|
||||
|
||||
played = cf_stats.games_won + cf_stats.games_lost
|
||||
|
||||
if played == 0:
|
||||
return await ctx.reply("This user hasn't played any games yet.", mention_author=False)
|
||||
|
||||
embed.add_field(name="Games played", value=played)
|
||||
embed.add_field(
|
||||
name="Winrate", value=f"{round(100 * cf_stats.games_won / played, 2)}% ({cf_stats.games_won}/{played})"
|
||||
)
|
||||
|
||||
embed.add_field(name="Dinks won", value=cf_stats.dinks_won)
|
||||
embed.add_field(name="Dinks lost", value=cf_stats.dinks_lost)
|
||||
embed.add_field(name="Profit", value=cf_stats.dinks_won - cf_stats.dinks_lost)
|
||||
|
||||
await ctx.reply(embed=embed, mention_author=False)
|
||||
|
||||
|
||||
async def setup(client: Didier):
|
||||
"""Load the cog"""
|
||||
await client.add_cog(Stats(client))
|
|
@ -0,0 +1,11 @@
|
|||
from didier.menus.common import Menu
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
class Leaderboard(Menu):
|
||||
pass
|
||||
|
||||
|
||||
class DinksLeaderboard(Leaderboard):
|
||||
pass
|
|
@ -12,10 +12,11 @@ from didier.utils.types.datetime import tz_aware_now
|
|||
|
||||
__all__ = ["Timer"]
|
||||
|
||||
|
||||
REMINDER_PREDELAY = timedelta(minutes=settings.REMINDER_PRE)
|
||||
|
||||
|
||||
# TODO make this generic
|
||||
# TODO add timer for jail freeing
|
||||
class Timer:
|
||||
"""Class for scheduled timers"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue