Game: using asyncio tasks to run in parallel operation that do not need to be sequential

This commit is contained in:
Elnath 2021-06-12 19:07:26 +02:00
parent 867f7c48eb
commit 15945d839c
1 changed files with 46 additions and 30 deletions

View File

@ -1,9 +1,10 @@
import asyncio
import logging
import random
from typing import Dict, Callable, List, Union
from functools import wraps
from collections import defaultdict
from enum import Enum
from functools import wraps
from typing import Dict, Callable, List, Union
import discord
@ -174,6 +175,8 @@ class Game:
if self.is_started():
raise ValueError("Game already started")
logger.info(f"[{self.guild.name}] Starting game")
tasks = [] # Asyncio tasks scheduled to run in parallel (e.g. channel creation), so that we can wait them all at the end of the function
self.config["game_started"] = True
self.config["gm_role"] = gm_role.id
self.config["player_role"] = player_role.id
self.config["players"] = [member.id for member in player_role.members]
@ -185,51 +188,62 @@ class Game:
self.config["drawn"] = None
self.config["enacted"] = []
permissions = {
category_permissions = {
self.guild.default_role: discord.PermissionOverwrite(send_messages = False),
gm_role: discord.PermissionOverwrite(send_messages = True),
player_role: discord.PermissionOverwrite(send_messages = True),
}
game_category = await self.guild.create_category("In-game", overwrites = permissions)
game_category = await self.guild.create_category("In-game", overwrites = category_permissions)
self.config["category"] = game_category.id
logger.debug(f"[{self.guild.name}] Created game category")
permissions = {
async def create_admin_chan():
perms = {
self.guild.default_role: discord.PermissionOverwrite(read_messages = False),
gm_role: discord.PermissionOverwrite(read_messages = True),
}
self.config["admin_chan"] = (await game_category.create_text_channel("admin", overwrites = permissions)).id
self.config["admin_chan"] = (await game_category.create_text_channel("admin", overwrites = perms, position = 0)).id
logger.debug(f"[{self.guild.name}] Created admin channel")
tasks.append(asyncio.create_task(create_admin_chan()))
permissions = {
async def create_announcements_and_vote_chans():
perms = {
self.guild.default_role: discord.PermissionOverwrite(send_messages = False),
gm_role: discord.PermissionOverwrite(send_messages = True),
}
self.config["announce_chan"] = (await game_category.create_text_channel("announce", overwrites = permissions)).id
self.config["votes_chan"] = (await game_category.create_text_channel("votes", overwrites = permissions)).id
channels = await asyncio.gather(
game_category.create_text_channel("announcements", overwrites = perms, position = 1),
game_category.create_text_channel("votes", overwrites = perms, position = 2)
)
self.config["announce_chan"] = channels[0].id
self.config["votes_chan"] = channels[1].id
logger.debug(f"[{self.guild.name}] Created announcements and votes channels")
tasks.append(asyncio.create_task(create_announcements_and_vote_chans()))
self.config["discussion_chan"] = (await game_category.create_text_channel("discussion")).id # Permissions are inherited from the category
async def create_discussion_chan():
# Permissions are inherited from the category
self.config["discussion_chan"] = (await game_category.create_text_channel("discussion", position = 3)).id # Permissions are inherited from the category
logger.debug(f"[{self.guild.name}] Created discussion channel")
tasks.append(asyncio.create_task(create_discussion_chan()))
for player in player_role.members:
channel_permissions = {
async def create_player_channel(player: discord.Member, position: int):
perms = {
self.guild.default_role: discord.PermissionOverwrite(read_messages = False),
player: discord.PermissionOverwrite(read_messages = True),
gm_role: discord.PermissionOverwrite(read_messages = True),
}
player_channel = await game_category.create_text_channel(player.name, overwrites = channel_permissions)
self.config["player_info"][str(player.id)]["channel"] = player_channel.id
logger.debug(f"[{self.guild.name}] Created player channels")
self.config["player_info"][str(player.id)]["channel"] = (await game_category.create_text_channel(player.name, overwrites = perms, position = position)).id
logger.debug(f"[{self.guild.name}] Created channel for player {player.name}")
for i, player in enumerate(player_role.members):
tasks.append(asyncio.create_task(create_player_channel(player, 4+i)))
self.config["game_started"] = True
await asyncio.wait(tasks)
@game_started
@save_on_success
async def delete(self):
category = self.get_game_category()
for channel in category.channels:
await channel.delete()
await asyncio.wait([channel.delete() for channel in category.channels])
await category.delete()
self.config.clear()
self.config.update(self.new_dict())
@ -292,10 +306,11 @@ class Game:
@save_on_success
async def stop_vote(self):
logging.debug(f"[{self.guild.name}] Stopping the vote")
tasks = []
passed = self.is_vote_passing()
self.config["vote"]["revealed"] = True
await self.update_vote_message()
await self.get_votes_channel().send("**The vote has ended**")
tasks.append(asyncio.create_task(self.get_votes_channel().send("**The vote has ended**")))
announcement_content = [
f"{self.get_player_role().mention} the vote has ended!",
f"{':green_square:' if passed else ':red_square:'} The vote has **{'' if passed else 'not '}passed**"
@ -304,7 +319,8 @@ class Game:
president = self.config["vote"]["president"]
chancellor = self.config["vote"]["chancellor"]
announcement_content.append(f"Congratulations to president <@{president}> and chancellor <@{chancellor}>!")
await self.get_announcements_channel().send("\n".join(announcement_content), allowed_mentions = discord.AllowedMentions(roles = True))
tasks.append(asyncio.create_task(self.get_announcements_channel().send("\n".join(announcement_content), allowed_mentions = discord.AllowedMentions(roles = True))))
await asyncio.wait(tasks)
self.config["vote"] = None
@game_started