Compare commits

..
Author SHA1 Message Date
imcompiling 2c5821e434 Merge branch '64-Limit-weekly-event-points'
build_release / build (push) Successful in 18s
build_latest / build (push) Successful in 17s
2024-05-19 22:32:52 -04:00
imcompiling cbfd6e20bc Move limit object management into separate function. Need to also get allowed points when creating a new quarter's event point tracker.
build_develop / build (push) Successful in 1m27s
2024-05-19 22:27:47 -04:00
imcompiling 34da664af0 Add a limit to the amount of event points one can earn weekly. 2024-05-19 22:09:10 -04:00
imcompiling c6c44afb76 Add table for limiting event points. 2024-05-19 12:05:43 -04:00
imcompiling c2d8239911 Revert "Rename ParticipationPoints table to EventPoints"
This reverts commit bec6494697.
2024-05-19 11:59:56 -04:00
imcompiling bec6494697 Rename ParticipationPoints table to EventPoints
build_develop / build (push) Successful in 1m21s
2024-05-19 11:52:25 -04:00
imcompiling 29a6b000ac Merge branch '49-view-votes-cant-see-HC-elections'
build_latest / build (push) Successful in 17s
build_release / build (push) Successful in 17s
2024-05-19 11:29:41 -04:00
imcompiling dbd2863aab Pass VoteType str instead of manual one in VoteSelect.
build_develop / build (push) Successful in 1m24s
2024-05-19 11:29:04 -04:00
imcompiling 426f009ca7 Use VoteType in utils. Remove old functions of getting clan leader and discord manager election names. 2024-05-19 10:50:23 -04:00
imcompiling ed07b2e231 Use VoteType in view command. 2024-05-19 10:46:05 -04:00
imcompiling 0caa41cc90 use VoteType in voting views. 2024-05-19 10:40:41 -04:00
imcompiling e93f37dcf0 Use VoteType in voting highcouncil views. 2024-05-19 10:38:10 -04:00
imcompiling 44c3961c46 Use VoteType in election_cycle 2024-05-19 10:31:16 -04:00
imcompiling 0dcdd038b8 Make the VoteType StrEnum and edit column in database to enforce only 3 values.
build_develop / build (push) Successful in 1m21s
2024-05-18 23:08:01 -04:00
imcompiling eb5d465ac9 Merge branch 'main' into 49--view-votes-can't-see-HC-elections
build_develop / build (push) Failing after 16s
2024-05-18 22:41:11 -04:00
imcompiling eb1c87fbf4 install sqlite3 onto container. Using it a lot for debugging/fixes.
build_latest / build (push) Successful in 1m29s
build_release / build (push) Successful in 22s
2024-05-18 22:38:57 -04:00
imcompiling cbd73a104e Merge branch '61-Create-virtual-environment-and-update-python-version' 2024-05-18 22:34:35 -04:00
imcompiling bc56830396 Merge branch '49--view-votes-can't-see-HC-elections' of https://gitea.cheezers.org/imcompiling/dakiny-bot into 49--view-votes-can't-see-HC-elections
build_develop / build (push) Failing after 17s
2024-05-18 16:36:03 -04:00
imcompiling 1d14f8171d Add vote type to one statement. 2024-05-18 16:34:33 -04:00
imcompiling 2efd380a7e Add VoteType Enum. 2024-05-18 16:26:11 -04:00
imcompiling 475170025a Edit database to add a type field to Votes. 2024-05-18 16:25:19 -04:00
imcompiling f4f3bfe103 Edit database to add a type field to Votes.
build_develop / build (push) Failing after 18s
2024-05-18 15:39:13 -04:00
10 changed files with 170 additions and 116 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
FROM python:3.11.9-slim FROM python:3.11.9-slim
# install dependencies # install dependencies
RUN apt-get update && apt-get -y upgrade && apt-get -y install git RUN apt-get update && apt-get -y upgrade && apt-get -y install git sqlite3
WORKDIR /home WORKDIR /home
+20 -10
View File
@@ -22,12 +22,11 @@ from database_setup.sql_data_classes import (
) )
from utils import ( from utils import (
TEMPLATES_DIR, TEMPLATES_DIR,
VoteType,
build_highcouncil_votes_str, build_highcouncil_votes_str,
build_votes_str, build_votes_str,
edit_clan_council_info, edit_clan_council_info,
get_cl_election_name,
get_datetime, get_datetime,
get_dm_election_name,
get_election_name, get_election_name,
) )
@@ -294,7 +293,11 @@ class ElectionCycle:
session.commit() session.commit()
# add the highcouncil role to everyone with 3 or more votes. set elected to true in database # add the highcouncil role to everyone with 3 or more votes. set elected to true in database
stmt = select(Votes.VotedForId).where(Votes.ElectionCycle == election_name) stmt = (
select(Votes.VotedForId)
.where(Votes.ElectionCycle == election_name)
.where(Votes.Type == VoteType.COUNCIL)
)
vote_count = collections.Counter(session.scalars(stmt)) vote_count = collections.Counter(session.scalars(stmt))
for user_id, votes in vote_count.items(): for user_id, votes in vote_count.items():
@@ -358,11 +361,13 @@ class ElectionCycle:
self.config.params.clan_council_role_id self.config.params.clan_council_role_id
) )
election_cycle = get_election_name(self.config)
with Session(engine) as session: with Session(engine) as session:
# role management # role management
stmt = ( stmt = (
select(CouncilMembers.MemberId) select(CouncilMembers.MemberId)
.where(CouncilMembers.ElectionCycle == get_election_name(self.config)) .where(CouncilMembers.ElectionCycle == election_cycle)
.where(CouncilMembers.Elected == true()) .where(CouncilMembers.Elected == true())
) )
@@ -379,14 +384,19 @@ class ElectionCycle:
# announce high council members # announce high council members
# ties are undefined behavior. # ties are undefined behavior.
dm_election = get_dm_election_name(self.config) stmt = (
cl_election = get_cl_election_name(self.config) select(Votes.VotedForId)
stmt = select(Votes.VotedForId).where(Votes.ElectionCycle == dm_election) .where(Votes.ElectionCycle == election_cycle)
.where(Votes.Type == VoteType.DISCORDMANAGER)
)
dm_votes = collections.Counter(session.scalars(stmt)) dm_votes = collections.Counter(session.scalars(stmt))
stmt = select(Votes.VotedForId).where(Votes.ElectionCycle == cl_election) stmt = (
select(Votes.VotedForId)
.where(Votes.ElectionCycle == election_cycle)
.where(Votes.Type == VoteType.CLANLEADER)
)
cl_votes = collections.Counter(session.scalars(stmt)) cl_votes = collections.Counter(session.scalars(stmt))
election_cycle = get_election_name(self.config)
try: try:
dm_winner = max(dm_votes, key=dm_votes.get) dm_winner = max(dm_votes, key=dm_votes.get)
stmt = ( stmt = (
@@ -425,7 +435,7 @@ class ElectionCycle:
await vote_msg.edit(view=None) await vote_msg.edit(view=None)
highcouncil_msg: str = ( highcouncil_msg: str = (
f"Congratulations for our high council members!\n Clan Leader: <@{cl_winner}>\n" f"Congratulations for our high council members!\nClan Leader: <@{cl_winner}>\n"
) )
highcouncil_msg += f"Discord Manager: <@{dm_winner}>" highcouncil_msg += f"Discord Manager: <@{dm_winner}>"
await election_thread.send(highcouncil_msg) await election_thread.send(highcouncil_msg)
+22 -28
View File
@@ -17,12 +17,7 @@ from database_setup.sql_data_classes import (
Votes, Votes,
engine, engine,
) )
from utils import ( from utils import VoteType, build_highcouncil_votes_str, get_election_name
build_highcouncil_votes_str,
get_cl_election_name,
get_dm_election_name,
get_election_name,
)
class VoteSelect(nextcord.ui.StringSelect): class VoteSelect(nextcord.ui.StringSelect):
@@ -39,20 +34,10 @@ class VoteSelect(nextcord.ui.StringSelect):
self.election_type = election_type self.election_type = election_type
async def callback(self, interaction: Interaction): async def callback(self, interaction: Interaction):
# decide on election type election_name: str = get_election_name(self.config)
match self.election_type:
case "cl":
election_name: str = get_cl_election_name(self.config)
case "dm":
election_name: str = get_dm_election_name(self.config)
case _:
# should never happen
raise ValueError('election type was not "cl" or "dm"')
cycle: str = get_election_name(self.config)
with Session(engine) as session: with Session(engine) as session:
stmt = select(ElectionInformation.HighCouncilVoteMsgId).where( stmt = select(ElectionInformation.HighCouncilVoteMsgId).where(
ElectionInformation.ElectionCycle == cycle ElectionInformation.ElectionCycle == election_name
) )
vote_msg_id = session.scalar(stmt) vote_msg_id = session.scalar(stmt)
@@ -65,6 +50,7 @@ class VoteSelect(nextcord.ui.StringSelect):
ElectionCycle=election_name, ElectionCycle=election_name,
VoterId=interaction.user.id, VoterId=interaction.user.id,
VotedForId=voted_for, VotedForId=voted_for,
Type=self.election_type,
) )
try: try:
@@ -72,11 +58,13 @@ class VoteSelect(nextcord.ui.StringSelect):
session.commit() session.commit()
except exc.IntegrityError: except exc.IntegrityError:
# user already has a vote in the election and election type
session.rollback() session.rollback()
stmt = ( stmt = (
update(Votes) update(Votes)
.where(Votes.ElectionCycle == election_name) .where(Votes.ElectionCycle == election_name)
.where(Votes.VoterId == interaction.user.id) .where(Votes.VoterId == interaction.user.id)
.where(Votes.Type == self.election_type)
.values(VotedForId=voted_for) .values(VotedForId=voted_for)
) )
session.execute(stmt) session.execute(stmt)
@@ -135,20 +123,20 @@ class VoteHighcouncilView(nextcord.ui.View):
) )
return return
cycle: str = get_election_name(self.config) election_name: str = get_election_name(self.config)
election: str = get_cl_election_name(self.config)
with Session(engine) as session: with Session(engine) as session:
stmt = ( stmt = (
select(Votes.VotedForId) select(Votes.VotedForId)
.where(Votes.ElectionCycle == election) .where(Votes.ElectionCycle == election_name)
.where(Votes.VoterId == interaction.user.id) .where(Votes.VoterId == interaction.user.id)
.where(Votes.Type == VoteType.CLANLEADER)
) )
voted_for = session.scalar(stmt) voted_for = session.scalar(stmt)
stmt = ( stmt = (
select(CouncilMembers.MemberId) select(CouncilMembers.MemberId)
.where(CouncilMembers.ElectionCycle == cycle) .where(CouncilMembers.ElectionCycle == election_name)
.filter(CouncilMembers.ClanLeaderSpeechId.is_not(None)) .filter(CouncilMembers.ClanLeaderSpeechId.is_not(None))
) )
@@ -175,7 +163,9 @@ class VoteHighcouncilView(nextcord.ui.View):
view = nextcord.ui.View() view = nextcord.ui.View()
view.add_item( view.add_item(
VoteSelect(options=options, config=self.config, election_type="cl") VoteSelect(
options=options, config=self.config, election_type=VoteType.CLANLEADER
)
) )
await interaction.response.send_message( await interaction.response.send_message(
@@ -213,20 +203,20 @@ class VoteHighcouncilView(nextcord.ui.View):
) )
return return
cycle: str = get_election_name(self.config) election_name: str = get_election_name(self.config)
election: str = get_dm_election_name(self.config)
with Session(engine) as session: with Session(engine) as session:
stmt = ( stmt = (
select(Votes.VotedForId) select(Votes.VotedForId)
.where(Votes.ElectionCycle == election) .where(Votes.ElectionCycle == election_name)
.where(Votes.VoterId == interaction.user.id) .where(Votes.VoterId == interaction.user.id)
.where(Votes.Type == VoteType.DISCORDMANAGER)
) )
voted_for = session.scalar(stmt) voted_for = session.scalar(stmt)
stmt = ( stmt = (
select(CouncilMembers.MemberId) select(CouncilMembers.MemberId)
.where(CouncilMembers.ElectionCycle == cycle) .where(CouncilMembers.ElectionCycle == election_name)
.filter(CouncilMembers.DiscordManagerSpeechId.is_not(None)) .filter(CouncilMembers.DiscordManagerSpeechId.is_not(None))
) )
@@ -253,7 +243,11 @@ class VoteHighcouncilView(nextcord.ui.View):
view = nextcord.ui.View() view = nextcord.ui.View()
view.add_item( view.add_item(
VoteSelect(options=options, config=self.config, election_type="dm") VoteSelect(
options=options,
config=self.config,
election_type=VoteType.DISCORDMANAGER,
)
) )
await interaction.response.send_message( await interaction.response.send_message(
+4 -1
View File
@@ -17,7 +17,7 @@ from database_setup.sql_data_classes import (
Votes, Votes,
engine, engine,
) )
from utils import build_votes_str, get_election_name from utils import VoteType, build_votes_str, get_election_name
class VoteSelect(nextcord.ui.StringSelect): class VoteSelect(nextcord.ui.StringSelect):
@@ -47,6 +47,7 @@ class VoteSelect(nextcord.ui.StringSelect):
ElectionCycle=election_name, ElectionCycle=election_name,
VoterId=interaction.user.id, VoterId=interaction.user.id,
VotedForId=voted_for, VotedForId=voted_for,
Type=VoteType.COUNCIL,
) )
try: try:
@@ -59,6 +60,7 @@ class VoteSelect(nextcord.ui.StringSelect):
update(Votes) update(Votes)
.where(Votes.ElectionCycle == election_name) .where(Votes.ElectionCycle == election_name)
.where(Votes.VoterId == interaction.user.id) .where(Votes.VoterId == interaction.user.id)
.where(Votes.Type == VoteType.COUNCIL)
.values(VotedForId=voted_for) .values(VotedForId=voted_for)
) )
session.execute(stmt) session.execute(stmt)
@@ -121,6 +123,7 @@ class VoteView(nextcord.ui.View):
select(Votes.VotedForId) select(Votes.VotedForId)
.where(Votes.ElectionCycle == election) .where(Votes.ElectionCycle == election)
.where(Votes.VoterId == interaction.user.id) .where(Votes.VoterId == interaction.user.id)
.where(Votes.Type == VoteType.COUNCIL)
) )
voted_for = session.scalar(stmt) voted_for = session.scalar(stmt)
+16 -4
View File
@@ -7,7 +7,7 @@ from discord import TextInputStyle
from nextcord.ext import commands from nextcord.ext import commands
from config import DakinyConfig 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"): class RecordCog(commands.Cog, name="Record Commands"):
@@ -129,14 +129,26 @@ class EventView(nextcord.ui.View):
discord_users_list: list[str] = [ discord_users_list: list[str] = [
str(user.id) for user in discord_users if user.id is not self.host_id 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 non_discord_users = interaction.message.embeds[0].fields[1].value
if non_discord_users: if non_discord_users:
non_discord_users_list: list[str] = non_discord_users.split("\n") 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( event_channel: nextcord.TextChannel = interaction.guild.get_channel(
self.config.params.event_post_channel_id self.config.params.event_post_channel_id
+11 -1
View File
@@ -14,6 +14,7 @@ from database_setup.sql_data_classes import (
Votes, Votes,
engine, engine,
) )
from utils import VoteType
class ViewCog(commands.Cog, name="View Commands"): class ViewCog(commands.Cog, name="View Commands"):
@@ -148,6 +149,11 @@ class ViewCog(commands.Cog, name="View Commands"):
election_name: str = nextcord.SlashOption( election_name: str = nextcord.SlashOption(
required=True, description="The election you want to view votes for." required=True, description="The election you want to view votes for."
), ),
election_type: str = nextcord.SlashOption(
required=True,
description="The election type. Council, Discord Manager, or Clan Leader.",
choices=VoteType,
),
): ):
""" """
Takes in an election name and sends a response message to the user with a list of people who voted in that Takes in an election name and sends a response message to the user with a list of people who voted in that
@@ -159,7 +165,11 @@ class ViewCog(commands.Cog, name="View Commands"):
election_name (str): Is SlashOption. The name of the election to view votes for. election_name (str): Is SlashOption. The name of the election to view votes for.
""" """
stmt = select(Votes).where(Votes.ElectionCycle == election_name) stmt = (
select(Votes)
.where(Votes.ElectionCycle == election_name)
.where(Votes.Type == election_type)
)
with Session(engine) as session: with Session(engine) as session:
# Check if election exists. # Check if election exists.
+1
View File
@@ -21,6 +21,7 @@ class Params:
event_host_points: int event_host_points: int
event_host_role_id: int event_host_role_id: int
event_participate_points: int event_participate_points: int
event_points_weekly_limit: int
event_post_channel_id: int event_post_channel_id: int
general_channel_id: int general_channel_id: int
git_branch: str git_branch: str
+9 -1
View File
@@ -25,8 +25,9 @@ CREATE TABLE Votes(
ElectionCycle varchar(30) not null, ElectionCycle varchar(30) not null,
VoterId bigint unsigned not null, VoterId bigint unsigned not null,
VotedForId bigint unsigned, VotedForId bigint unsigned,
Type varchar(14) not null DEFAULT 'council' check("Type" in ('council', 'discordmanager', 'clanleader')),
FOREIGN KEY (ElectionCycle) REFERENCES ElectionInformation(ElectionCycle), FOREIGN KEY (ElectionCycle) REFERENCES ElectionInformation(ElectionCycle),
PRIMARY KEY (ElectionCycle, VoterId) PRIMARY KEY (ElectionCycle, VoterId, Type)
); );
CREATE TABLE UserBirthday ( CREATE TABLE UserBirthday (
@@ -52,3 +53,10 @@ CREATE TABLE Messages (
Path varchar(100) PRIMARY KEY, Path varchar(100) PRIMARY KEY,
Id bigint unsigned not null Id bigint unsigned not null
); );
CREATE TABLE EventPointsLimit (
UserId varchar(32) not null,
Points int unsigned DEFAULT 0,
Week varchar(7) not null,
PRIMARY KEY (UserId, Week)
);
+1
View File
@@ -14,6 +14,7 @@ Base.prepare(autoload_with=engine)
# define the classes # define the classes
CouncilMembers = Base.classes.CouncilMembers CouncilMembers = Base.classes.CouncilMembers
ElectionInformation = Base.classes.ElectionInformation ElectionInformation = Base.classes.ElectionInformation
EventPointsLimit = Base.classes.EventPointsLimit
Messages = Base.classes.Messages Messages = Base.classes.Messages
ParticipationPoints = Base.classes.ParticipationPoints ParticipationPoints = Base.classes.ParticipationPoints
Presences = Base.classes.Presences Presences = Base.classes.Presences
+85 -70
View File
@@ -4,7 +4,8 @@ File contains util functions.
import os import os
from datetime import datetime from datetime import datetime
from typing import Iterable from enum import StrEnum
from typing import Sequence
import nextcord import nextcord
from sqlalchemy import select, true, update from sqlalchemy import select, true, update
@@ -13,6 +14,7 @@ from sqlalchemy.orm import Session
from config import DakinyConfig from config import DakinyConfig
from database_setup.sql_data_classes import ( from database_setup.sql_data_classes import (
CouncilMembers, CouncilMembers,
EventPointsLimit,
Messages, Messages,
ParticipationPoints, ParticipationPoints,
Votes, Votes,
@@ -24,6 +26,8 @@ REPO_DIR = "./dakiny-messages"
MESSAGES_DIR = f"{REPO_DIR}/messages" MESSAGES_DIR = f"{REPO_DIR}/messages"
TEMPLATES_DIR = f"{REPO_DIR}/message_templates" TEMPLATES_DIR = f"{REPO_DIR}/message_templates"
VoteType = StrEnum("VoteType", ["COUNCIL", "DISCORDMANAGER", "CLANLEADER"])
def get_datetime(day: str) -> datetime: def get_datetime(day: str) -> datetime:
""" """
@@ -82,34 +86,6 @@ def get_quarter_name(config: DakinyConfig) -> str:
return f"{get_datetime(current_cycle.term_start).year}-{current_cycle.name}" return f"{get_datetime(current_cycle.term_start).year}-{current_cycle.name}"
def get_dm_election_name(config: DakinyConfig) -> str:
"""
creates the name of the discord manager election
Args:
config (DakinyConfig): Config sent to get_election_cycle_name
Returns:
str: the name of the election
"""
return f"{get_election_name(config)}-dm"
def get_cl_election_name(config: DakinyConfig) -> str:
"""
creates the name of the clan leader election
Args:
config (DakinyConfig): Config sent to get_election_cycle_name
Returns:
str: the name of the election
"""
return f"{get_election_name(config)}-cl"
def get_current_election_cycle(config: DakinyConfig) -> int: def get_current_election_cycle(config: DakinyConfig) -> int:
""" """
Returns index for active election. An election is considered active between the election start and the term start. Returns index for active election. An election is considered active between the election start and the term start.
@@ -170,9 +146,11 @@ def build_votes_str(config: DakinyConfig, guild: nextcord.Guild) -> str:
votes: dict[int, int] = {} votes: dict[int, int] = {}
election_name = get_election_name(config)
with Session(engine) as session: with Session(engine) as session:
stmt = select(CouncilMembers).where( stmt = select(CouncilMembers).where(
CouncilMembers.ElectionCycle == get_election_name(config) CouncilMembers.ElectionCycle == election_name
) )
for nominee in sorted( for nominee in sorted(
@@ -181,7 +159,11 @@ def build_votes_str(config: DakinyConfig, guild: nextcord.Guild) -> str:
): ):
votes[nominee.MemberId] = 0 votes[nominee.MemberId] = 0
stmt = select(Votes).where(Votes.ElectionCycle == get_election_name(config)) stmt = (
select(Votes)
.where(Votes.ElectionCycle == election_name)
.where(Votes.Type == VoteType.COUNCIL)
)
for vote in session.scalars(stmt): for vote in session.scalars(stmt):
if vote.VotedForId is not None: if vote.VotedForId is not None:
@@ -208,10 +190,12 @@ def build_highcouncil_votes_str(config: DakinyConfig, guild: nextcord.Guild) ->
cl_votes: dict[int, int] = {} cl_votes: dict[int, int] = {}
dm_votes: dict[int, int] = {} dm_votes: dict[int, int] = {}
election_name = get_election_name(config)
with Session(engine) as session: with Session(engine) as session:
stmt = ( stmt = (
select(CouncilMembers) select(CouncilMembers)
.where(CouncilMembers.ElectionCycle == get_election_name(config)) .where(CouncilMembers.ElectionCycle == election_name)
.filter(CouncilMembers.ClanLeaderSpeechId.is_not(None)) .filter(CouncilMembers.ClanLeaderSpeechId.is_not(None))
) )
@@ -221,7 +205,11 @@ def build_highcouncil_votes_str(config: DakinyConfig, guild: nextcord.Guild) ->
): ):
cl_votes[nominee.MemberId] = 0 cl_votes[nominee.MemberId] = 0
stmt = select(Votes).where(Votes.ElectionCycle == get_cl_election_name(config)) stmt = (
select(Votes)
.where(Votes.ElectionCycle == election_name)
.where(Votes.Type == VoteType.CLANLEADER)
)
for vote in session.scalars(stmt): for vote in session.scalars(stmt):
if vote.VotedForId is not None: if vote.VotedForId is not None:
@@ -229,7 +217,7 @@ def build_highcouncil_votes_str(config: DakinyConfig, guild: nextcord.Guild) ->
stmt = ( stmt = (
select(CouncilMembers) select(CouncilMembers)
.where(CouncilMembers.ElectionCycle == get_election_name(config)) .where(CouncilMembers.ElectionCycle == election_name)
.filter(CouncilMembers.DiscordManagerSpeechId.is_not(None)) .filter(CouncilMembers.DiscordManagerSpeechId.is_not(None))
) )
@@ -239,7 +227,11 @@ def build_highcouncil_votes_str(config: DakinyConfig, guild: nextcord.Guild) ->
): ):
dm_votes[nominee.MemberId] = 0 dm_votes[nominee.MemberId] = 0
stmt = select(Votes).where(Votes.ElectionCycle == get_dm_election_name(config)) stmt = (
select(Votes)
.where(Votes.ElectionCycle == election_name)
.where(Votes.Type == VoteType.DISCORDMANAGER)
)
for vote in session.scalars(stmt): for vote in session.scalars(stmt):
if vote.VotedForId is not None: if vote.VotedForId is not None:
@@ -326,76 +318,98 @@ def decorate_dm_nomination(user_id: int, speech: str) -> str:
return msg 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, add_points: int
):
""" """
Adds participation points to all users listed. Checks if they don't exist in order to make a new entry, otherwise 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. adds points to the existing value. Can be used for hosting or participating.
Args: Args:
config (DakinyConfig): Dakiny config for getting points 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 is_member (bool): whether the users are a discord member or not
points (int): number of points to add
""" """
cycle = get_quarter_name(config) quarter_name = get_quarter_name(config)
participation_point_value = config.params.event_participate_points
with Session(engine) as session: with Session(engine) as session:
for user in users: for user in users:
stmt = ( stmt = (
select(ParticipationPoints) select(ParticipationPoints)
.where(ParticipationPoints.UserId == user) .where(ParticipationPoints.UserId == user)
.where(ParticipationPoints.Cycle == cycle) .where(ParticipationPoints.Cycle == quarter_name)
) )
points = session.scalar(stmt) points = session.scalar(stmt)
if points is None: if points is None:
add_points = get_allowed_points(
session, config.params.event_points_weekly_limit, user, add_points
)
new_points = ParticipationPoints( new_points = ParticipationPoints(
Cycle=cycle, Cycle=quarter_name,
UserId=user, UserId=user,
DiscordMember=is_member, DiscordMember=is_member,
Points=participation_point_value, Points=add_points,
) )
session.add(new_points) session.add(new_points)
else: else:
points.Points += participation_point_value add_points = get_allowed_points(
session, config.params.event_points_weekly_limit, user, add_points
)
points.Points += add_points
session.commit() session.commit()
def record_event_host(config: DakinyConfig, user: int): def get_allowed_points(
session: Session, points_limit: int, user: str, points: int
) -> int:
""" """
Adds host points to the given user. Checks if they don't exist in order to make a new entry, otherwise adds points Gets the maximum number of points a user can be given. Searches how many points they have been given
to the existing value. this week and subtracts that from the weekly limit. If under, returns up to "points" number of points (will not
go over points_limit) otherwise returns 0. Updates the limit object or creates a new one if one isn't found.
Args: Args:
config (DakinyConfig): Dakiny config for getting points session (Session): Open connection to database.
user (int): Id of user that hosted. points_limit (int): Maximum number of points a user can be given in a week.
user (str): user to be given points. Used to check a user's limit.
points (int): maximum number of points to give to user.
Returns:
int: how many points are allowed to be given to the user.
""" """
cycle = get_quarter_name(config) # check for limit
host_point_value = config.params.event_host_points this_week = (
with Session(engine) as session: f"{datetime.today().isocalendar().year}-{datetime.today().isocalendar().week}"
stmt = ( )
select(ParticipationPoints) stmt = (
.where(ParticipationPoints.UserId == str(user)) select(EventPointsLimit)
.where(ParticipationPoints.Cycle == cycle) .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)
if limit is None:
new_limit = EventPointsLimit(UserId=user, Points=points, Week=this_week)
add_points = points
session.add(new_limit)
else:
add_points = (
points
if limit.Points + points <= points_limit
else (points_limit - limit.Points if points_limit - limit.Points > 0 else 0)
) )
limit.Points += add_points
points = session.scalar(stmt) session.commit()
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() return add_points
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. Updates all clan messages to contents in MESSAGES_DIR.
Does not to any git work. Is expected to be called after git is pulled. Does not to any git work. Is expected to be called after git is pulled.
@@ -407,6 +421,7 @@ async def update_clan_messages(guild: nextcord.Guild, channel_updates: Iterable[
Args: Args:
guild (nextcord.Guild): Guild object that all channels and messages belong to. guild (nextcord.Guild): Guild object that all channels and messages belong to.
channel_updates: (Sequence[str]): a sequence of the channels to update.
""" """
dirs = [ dirs = [