diff --git a/cogs/commands/record.py b/cogs/commands/record.py index 66afef0..2e53b23 100644 --- a/cogs/commands/record.py +++ b/cogs/commands/record.py @@ -7,7 +7,7 @@ from discord import TextInputStyle from nextcord.ext import commands from config import DakinyConfig -from utils import record_event_host, record_event_participation +from utils import record_event_points class RecordCog(commands.Cog, name="Record Commands"): @@ -129,14 +129,26 @@ class EventView(nextcord.ui.View): discord_users_list: list[str] = [ str(user.id) for user in discord_users if user.id is not self.host_id ] - record_event_participation(self.config, discord_users_list, True) + record_event_points( + self.config, + discord_users_list, + True, + self.config.params.event_participate_points, + ) non_discord_users = interaction.message.embeds[0].fields[1].value if non_discord_users: non_discord_users_list: list[str] = non_discord_users.split("\n") - record_event_participation(self.config, non_discord_users_list, False) + record_event_points( + self.config, + non_discord_users_list, + False, + self.config.params.event_participate_points, + ) - record_event_host(self.config, self.host_id) + record_event_points( + self.config, [self.host_id], True, self.config.params.event_host_points + ) event_channel: nextcord.TextChannel = interaction.guild.get_channel( self.config.params.event_post_channel_id diff --git a/config.py b/config.py index 6510907..84b2144 100644 --- a/config.py +++ b/config.py @@ -21,6 +21,7 @@ class Params: event_host_points: int event_host_role_id: int event_participate_points: int + event_points_weekly_limit: int event_post_channel_id: int general_channel_id: int git_branch: str diff --git a/database_setup/sql_data_classes.py b/database_setup/sql_data_classes.py index 007d432..67411f3 100644 --- a/database_setup/sql_data_classes.py +++ b/database_setup/sql_data_classes.py @@ -14,6 +14,7 @@ Base.prepare(autoload_with=engine) # define the classes CouncilMembers = Base.classes.CouncilMembers ElectionInformation = Base.classes.ElectionInformation +EventPointsLimit = Base.classes.EventPointsLimit Messages = Base.classes.Messages ParticipationPoints = Base.classes.ParticipationPoints Presences = Base.classes.Presences diff --git a/utils.py b/utils.py index 3caba58..237c4db 100644 --- a/utils.py +++ b/utils.py @@ -5,7 +5,7 @@ File contains util functions. import os from datetime import datetime from enum import StrEnum -from typing import Iterable +from typing import Sequence import nextcord from sqlalchemy import select, true, update @@ -14,6 +14,7 @@ from sqlalchemy.orm import Session from config import DakinyConfig from database_setup.sql_data_classes import ( CouncilMembers, + EventPointsLimit, Messages, ParticipationPoints, Votes, @@ -317,19 +318,21 @@ def decorate_dm_nomination(user_id: int, speech: str) -> str: return msg -def record_event_participation(config: DakinyConfig, users: list[str], is_member: bool): +def record_event_points( + config: DakinyConfig, users: Sequence[str], is_member: bool, points: int +): """ - Adds participation points to all users listed. Checks if they don't exist in order to make a new entry, otherwise - adds points to the existing value. + Adds event points to all users listed. Checks if they don't exist in order to make a new entry, otherwise + adds points to the existing value. Can be used for hosting or participating. Args: config (DakinyConfig): Dakiny config for getting points - users (list[int]): users that participated and need points. + users (Sequence[int]): users that participated and need points. is_member (bool): whether the users are a discord member or not + points (int): number of points to add """ cycle = get_quarter_name(config) - participation_point_value = config.params.event_participate_points with Session(engine) as session: for user in users: stmt = ( @@ -344,49 +347,38 @@ def record_event_participation(config: DakinyConfig, users: list[str], is_member Cycle=cycle, UserId=user, DiscordMember=is_member, - Points=participation_point_value, + Points=points, ) session.add(new_points) else: - points.Points += participation_point_value + # check for limit + this_week = f"{datetime.today().isocalendar().year}-{datetime.today().isocalendar().week}" + stmt = ( + select(EventPointsLimit) + .where(EventPointsLimit.UserId == user) + .where(EventPointsLimit.Week == this_week) + ) + + # if under limit, can add up to however many points would make the current limit equal to the + # allowed limit. + limit = session.scalar(stmt) + add_points = ( + points + if limit.Points + points <= config.params.event_points_weekly_limit + else ( + config.params.event_points_weekly_limit - limit.Points + if config.params.event_points_weekly_limit - limit.Points > 0 + else 0 + ) + ) + + limit.Points += add_points + points.Points += add_points session.commit() -def record_event_host(config: DakinyConfig, user: int): - """ - Adds host points to the given user. Checks if they don't exist in order to make a new entry, otherwise adds points - to the existing value. - - Args: - config (DakinyConfig): Dakiny config for getting points - user (int): Id of user that hosted. - """ - cycle = get_quarter_name(config) - host_point_value = config.params.event_host_points - with Session(engine) as session: - stmt = ( - select(ParticipationPoints) - .where(ParticipationPoints.UserId == str(user)) - .where(ParticipationPoints.Cycle == cycle) - ) - - points = session.scalar(stmt) - if points is None: - new_points = ParticipationPoints( - Cycle=cycle, - UserId=str(user), - DiscordMember=True, - Points=host_point_value, - ) - session.add(new_points) - else: - points.Points += host_point_value - - session.commit() - - -async def update_clan_messages(guild: nextcord.Guild, channel_updates: Iterable[str]): +async def update_clan_messages(guild: nextcord.Guild, channel_updates: Sequence[str]): """ Updates all clan messages to contents in MESSAGES_DIR. Does not to any git work. Is expected to be called after git is pulled. @@ -398,6 +390,7 @@ async def update_clan_messages(guild: nextcord.Guild, channel_updates: Iterable[ Args: guild (nextcord.Guild): Guild object that all channels and messages belong to. + channel_updates: (Sequence[str]): a sequence of the channels to update. """ dirs = [