async def start_round(self, ctx, days, pool): state = await State.fetch(self, ctx, allow_started=True) last_round = await state.cc.fetch_last_round() if last_round is not None and not last_round.is_finished: raise BotErr(f'Finish round {last_round.num} first.') pool = await state.fetch_pool(pool) users_participants = await state.cc.fetch_users_participants() users = { up[0].id: up[0] for up in users_participants } participants = [ up[1] for up in filter(lambda up: not up[1].has_failed(), users_participants) ] BotErr.raise_if(len(participants) == 0, 'Not enough participants to start a round.') titles = await pool.fetch_unused_titles() BotErr.raise_if(len(titles) < len(participants), f'Not enough titles in "{pool}" pool.') num = last_round.num + 1 if last_round is not None else 0 start = datetime.now() new_round = await state.cc.add_round(num, start, start + timedelta(days=days)) rand_titles = [ titles.pop(random.randrange(len(titles))) for _ in range(len(participants)) ] for participant, title in zip(participants, rand_titles): await new_round.add_roll(participant.id, title.id) participant.progress_current = None participant.progress_total = None title.is_used = True await participant.update() await title.update() await self.db.commit() return new_round, { users[p.user_id].name: t.name for p, t in zip(participants, rand_titles) }
async def start_challenge(self, ctx, name): guild = await Guild.fetch_or_insert(self.db, ctx.message.guild.id) if guild.current_challenge_id is not None: raise BotErr(f'Finish "{(await guild.fetch_current_challenge()).name}" challenge first.') BotErr.raise_if(await guild.has_challenge(name), f'Challenge "{name}" already exists.') challenge = await guild.add_challenge(name, datetime.now()) await challenge.add_pool('main') guild.current_challenge_id = challenge.id await guild.update() await self.db.commit()