Ejemplo n.º 1
0
 def count_vote(self, ind: int, user: discord.Member, vid: int,
                limit: int) -> str:
     role_name = voteDB.getOptions(vid)[ind]
     # print(role_name[1].lower(), [r.name.lower() for r in user.roles])
     role: discord.Role = next(
         (r for r in user.roles if role_name[1].lower() == r.name.lower()),
         None)
     if not role: return "added vote"
     else: return "removed vote"
Ejemplo n.º 2
0
    def make_results(self, vid: int,
                     num_win: int) -> list[Union[discord.File, EmbedData]]:
        """
        Makes result list for vote
        :param vid: Vote ID
        :return: List of embed parts
        """

        # Get votes from DB
        votes = voteDB.getUserVotes(vid)

        # Group by user in dict
        user_prefs = defaultdict(dict)
        for uid, choice, pref in votes:
            user_prefs[uid][pref] = choice

        # Convert dict to list
        counts = Counter()
        first_pref = Counter()
        for uid, ord_dict in user_prefs.items():
            uv = []
            for k in sorted(ord_dict.keys()):
                for i in range(len(uv) - 1, k, 1):
                    uv.append(0)
                uv[k] = ord_dict[k]
            counts[tuple(uv)] += 1
            first_pref[uv[0]] += 1

        options = [x[1] for x in voteDB.getOptions(vid)]
        indexes = list(range(len(options)))
        print("Votes parcelled ", counts, first_pref)
        vote = stv.STV(indexes.copy(), counts, num_win)

        # Make file of votes
        file = io.StringIO()
        print("Count: pref1, pref2, pref3,...", file=file)
        for k, v in vote.preferences.items():
            print(f"{v}: {', '.join(map(str, k))}", file=file)

        print(file.getvalue())
        winners = vote.run()
        print("STV Run, winners are", winners)

        first_prefs = indexes.copy()
        first_prefs.sort(key=lambda x: -first_pref[x])

        return [
            discord.File(file, filename=f"{vid}.votes"),
            ("STV Winners",
             [f"{symbols[i]} **{options[i]}**"
              for i in winners] if winners else ["No winners."], False),
            self.list_results(options, first_prefs, first_pref,
                              "First Preference Votes")
        ]
Ejemplo n.º 3
0
    async def give_feedback(self, result, user: discord.Member, index, vid,
                            limit):
        await user.create_dm()
        print(f"Sending DM for {result} to {user}")

        options = [x[1] for x in voteDB.getOptions(vid)]

        if isinstance(result, tuple) and result[0] == "clear votes":
            await user.dm_channel.send(
                f"Reaction Action {vid}: Your roles have been cleared for:\n\t\t"
                + '\n\t\t'.join(f"{symbols[i]} **{options[i]}**"
                                for i in result[1]))

        elif result == "added vote":
            role_name = voteDB.getOptions(vid)[index]
            role: discord.Role = next(
                (r for r in user.guild.roles
                 if role_name[1].lower() == r.name.lower()), None)
            await user.add_roles(role, atomic=True)
            await user.dm_channel.send(
                f"Reaction Action {vid}: Added role {symbols[index]} **{options[index]}**"
            )

        elif result == "removed vote":
            role_name = voteDB.getOptions(vid)[index]
            role: discord.Role = next(
                (r for r in user.roles
                 if role_name[1].lower() == r.name.lower()), None)
            await user.remove_roles(role, atomic=True)
            await user.dm_channel.send(
                f"Reaction Action {vid}: Removed role {symbols[index]} **{options[index]}**"
            )

        elif result == "over limit":
            await user.dm_channel.send(
                f"Poll {vid}: Your vote for **{options[index]}** was **not counted**. You have voted for the **maximum of {limit}** choices. \n"
                f"\t\t**Remove a vote** before voting again: \n\t\tYour current choices are:\n\t\t\t"
                +
                '\n\t\t\t'.join(f"{symbols[i]} **{options[i]}**"
                                for i, _ in voteDB.getUserVotes(vid, user.id)))
Ejemplo n.º 4
0
    async def myvotes(self, ctx: Context, vid: int):
        user = ctx.author
        await user.create_dm()

        options = [x[1] for x in voteDB.getOptions(vid)]
        uvs = voteDB.getUserVotes(vid, user.id)

        if not uvs:
            await user.dm_channel.send(f"Poll {vid}: You have no votes so far."
                                       )
        else:
            await user.dm_channel.send(
                f"Poll {vid}: Your current votes are:\n\t\t" +
                '\n\t\t'.join(f"{symbols[i]} **{options[i]}**"
                              for i, _ in uvs))
Ejemplo n.º 5
0
    async def give_feedback(self, result, user: discord.Member, index, vid,
                            limit):
        """
        Sends DM to user with result of reaction
        :param result: str with result of reaction
        :param user: user to send DM to
        :param index: index of option, -1 if wrong (ignored) or index of choice. If clear, list of indexes removed
        :param vid: vote ID
        :param limit: vote limit
        """
        await user.create_dm()
        print(f"Sending DM for {result} to {user}")

        options = [x[1] for x in voteDB.getOptions(vid)]
        user_votes = [
            x[0] for x in sorted(voteDB.getUserVotes(vid, user.id),
                                 key=lambda x: x[1])
        ]

        if result == "added vote":
            await user.dm_channel.send(
                f"Poll {vid}: Counted your vote for {symbols[index]} **{options[index]}** at preference {user_votes.index(index)+1}.\n"
                f"Your order: " + ', '.join(symbols[c]
                                            for i, c in enumerate(user_votes)))
        elif result == "removed vote":
            await user.dm_channel.send(
                f"Poll {vid}: Removed your vote for {symbols[index]} **{options[index]}**"
            )
        elif result == "over limit":
            await user.dm_channel.send(
                f"Poll {vid}: Your vote for **{options[index]}** was **not counted**. "
                f"You have voted for the **maximum of {limit}** choices. \n"
                f"\t\t**Remove a vote** before voting again: \n\t\tYour current choices are:\n\t\t\t"
                + '\n\t\t\t'.join(f"{symbols[i]} **{options[i]}**"
                                  for i in user_votes))
        elif result == "clear votes":
            await user.dm_channel.send(
                f"Poll {vid}: Your votes have been cleared for:\n\t\t" +
                '\n\t\t'.join(f"{symbols[i]} **{options[i]}**" for i in index))
        elif result == "already counted":
            await user.dm_channel.send(
                f"Poll {vid}: You have **already voted** for {options[index]} option as preference #{user_votes.index(index)+1}. "
                f"To change your ordering, **clear votes** and enter your updated order.\n"
                f"your current preferences are:\n\t\t" +
                '\n\t\t'.join(f"{i+1}: {symbols[c]} **{options[c]}**"
                              for i, c in enumerate(user_votes)))
Ejemplo n.º 6
0
    def make_results(self, vid: int,
                     num_win: int) -> list[Union[discord.File, EmbedData]]:
        """
        Makes result list for vote
        :param vid: Vote ID
        :return: List of embed parts
        """
        votes = dict(voteDB.getUserVoteCount(vid))
        options = ["" for _ in range(len(votes))]
        for i, text in voteDB.getOptions(vid):
            options[i] = text

        sections = [
            StdVote.top_n_results(num_win, options, votes, title="Winners")
        ]
        if num_win < 5:
            sections.append(StdVote.top_n_results(5, options, votes))
        sections.append(
            StdVote.list_results(options, list(range(len(options))), votes))

        return sections
Ejemplo n.º 7
0
    async def give_feedback(self, result, user: discord.Member, index, vid,
                            limit):
        """
        Sends DM to user with result of reaction
        :param result: str with result of reaction
        :param user: user to send DM to
        :param index: index of option, -1 if wrong (ignored) or index of choice. If clear, list of indexes removed
        :param vid: vote ID
        :param limit: vote limit
        """
        await user.create_dm()
        print(f"Sending DM for {result} to {user}")

        options = [x[1] for x in voteDB.getOptions(vid)]

        if isinstance(result, tuple) and result[0] == "clear votes":
            await user.dm_channel.send(
                f"Poll {vid}: Your votes have been cleared for:\n\t\t" +
                '\n\t\t'.join(f"{symbols[i]} **{options[i]}**"
                              for i in result[1]))

        elif result == "added vote":
            await user.dm_channel.send(
                f"Poll {vid}: Counted your vote for {symbols[index]} **{options[index]}**"
            )
        elif result == "removed vote":
            await user.dm_channel.send(
                f"Poll {vid}: Removed your vote for {symbols[index]} **{options[index]}**"
            )

        elif result == "over limit":
            await user.dm_channel.send(
                f"Poll {vid}: Your vote for **{options[index]}** was **not counted**. You have voted for the **maximum of {limit}** choices. \n"
                f"\t\t**Remove a vote** before voting again: \n\t\tYour current choices are:\n\t\t\t"
                +
                '\n\t\t\t'.join(f"{symbols[i]} **{options[i]}**"
                                for i, _ in voteDB.getUserVotes(vid, user.id)))