Esempio n. 1
0
    def _make_standings_pages(self, contest, problem_indices, handle_standings, deltas=None):
        pages = []
        handle_standings_chunks = paginator.chunkify(handle_standings, _STANDINGS_PER_PAGE)
        num_chunks = len(handle_standings_chunks)
        delta_chunks = paginator.chunkify(deltas, _STANDINGS_PER_PAGE) if deltas else [None] * num_chunks

        if contest.type == 'CF':
            get_table = functools.partial(self._get_cf_or_ioi_standings_table, mode='cf')
        elif contest.type == 'ICPC':
            get_table = self._get_icpc_standings_table
        elif contest.type == 'IOI':
            get_table = functools.partial(self._get_cf_or_ioi_standings_table, mode='ioi')
        else:
            assert False, f'Unexpected contest type {contest.type}'

        num_pages = 1
        for handle_standings_chunk, delta_chunk in zip(handle_standings_chunks, delta_chunks):
            header_style, body_style, header, body = get_table(problem_indices,
                                                               handle_standings_chunk,
                                                               delta_chunk)
            t = table.Table(table.Style(header=header_style, body=body_style))
            t += table.Header(*header)
            t += table.Line('\N{EM DASH}')
            for row in body:
                t += table.Data(*row)
            t += table.Line('\N{EM DASH}')
            page_num_footer = f' # Page: {num_pages} / {num_chunks}' if num_chunks > 1 else ''

            # We use yaml to get nice colors in the ranklist.
            content = f'```yaml\n{t}\n{page_num_footer}```'
            pages.append((content, None))
            num_pages += 1

        return pages
Esempio n. 2
0
    async def vc(self, ctx, *args: str):
        """Recommends a contest based on Codeforces rating of the handle provided.
        e.g ;vc mblazev c1729 +global +hello +goodbye +avito"""
        markers = [x for x in args if x[0] == '+']
        handles = [x for x in args if x[0] != '+'] or ('!' + str(ctx.author), )
        handles = await cf_common.resolve_handles(ctx,
                                                  self.converter,
                                                  handles,
                                                  maxcnt=25)
        info = await cf.user.info(handles=handles)
        contests = cf_common.cache2.contest_cache.get_contests_in_phase(
            'FINISHED')

        if not markers:
            divr = sum(user.effective_rating for user in info) / len(handles)
            div1_indicators = ['div1', 'global', 'avito', 'goodbye', 'hello']
            markers = [
                'div3'
            ] if divr < 1600 else ['div2'] if divr < 2100 else div1_indicators

        recommendations = {
            contest.id
            for contest in contests if contest.matches(markers)
            and not cf_common.is_nonstandard_contest(contest) and not any(
                cf_common.is_contest_writer(contest.id, handle)
                for handle in handles)
        }

        # Discard contests in which user has non-CE submissions.
        visited_contests = await cf_common.get_visited_contests(handles)
        recommendations -= visited_contests

        if not recommendations:
            raise CodeforcesCogError('Unable to recommend a contest')

        recommendations = list(recommendations)
        random.shuffle(recommendations)
        contests = [
            cf_common.cache2.contest_cache.get_contest(contest_id)
            for contest_id in recommendations[:25]
        ]

        def make_line(c):
            return f'[{c.name}]({c.url}) {cf_common.pretty_time_format(c.durationSeconds)}'

        def make_page(chunk):
            str_handles = '`, `'.join(handles)
            message = f'Recommended contest(s) for `{str_handles}`'
            vc_str = '\n'.join(make_line(contest) for contest in chunk)
            embed = discord_common.cf_color_embed(description=vc_str)
            return message, embed

        pages = [make_page(chunk) for chunk in paginator.chunkify(contests, 5)]
        paginator.paginate(self.bot,
                           ctx.channel,
                           pages,
                           wait_time=5 * 60,
                           set_pagenum_footers=True)
Esempio n. 3
0
 def _make_contest_pages(contests, title):
     pages = []
     chunks = paginator.chunkify(contests, _CONTESTS_PER_PAGE)
     for chunk in chunks:
         embed = discord_common.cf_color_embed()
         for name, value in _get_embed_fields_from_contests(chunk):
             embed.add_field(name=name, value=value, inline=False)
         pages.append((title, embed))
     return pages
Esempio n. 4
0
 async def fetch_missing_contests(self):
     """Fetch rating changes for contests which are not saved in database. Intended for
     manual trigger."""
     contests = self.cache_master.contest_cache.contests_by_phase['FINISHED']
     contests = [
         contest for contest in contests if not self.has_rating_changes_saved(contest.id)]
     total_changes = 0
     for contests_chunk in paginator.chunkify(contests, _CONTESTS_PER_BATCH_IN_CACHE_UPDATES):
         contests_chunk = await self._fetch(contests_chunk)
         self._save_changes(contests_chunk)
         total_changes += len(contests_chunk)
     return total_changes
Esempio n. 5
0
    async def stalk(self, ctx, *args):
        """Print problems solved by user sorted by time (default) or rating.
        All submission types are included by default (practice, contest, etc.)
        """
        (hardest, ), args = cf_common.filter_flags(args, ['+hardest'])
        filt = cf_common.SubFilter(False)
        args = filt.parse(args)
        handles = args
        handles = await cf_common.resolve_handles(ctx, self.converter, handles)
        submissions = [
            await cf.user.status(handle=handle) for handle in handles
        ]
        submissions = [sub for subs in submissions for sub in subs]
        submissions = filt.filter_subs(submissions)

        if not submissions:
            raise CodeforcesCogError(
                'Submissions not found within the search parameters')

        if hardest:
            submissions.sort(
                key=lambda sub:
                (sub.problem.rating or 0, sub.creationTimeSeconds),
                reverse=True)
        else:
            submissions.sort(key=lambda sub: sub.creationTimeSeconds,
                             reverse=True)

        def make_line(sub):
            data = (f'[{sub.problem.name}]({sub.problem.url})',
                    f'[{sub.problem.rating if sub.problem.rating else "?"}]',
                    f'({cf_common.days_ago(sub.creationTimeSeconds)})')
            return '\N{EN SPACE}'.join(data)

        def make_page(chunk):
            title = '{} solved problems by `{}`'.format(
                'Hardest' if hardest else 'Recently', '`, `'.join(handles))
            hist_str = '\n'.join(make_line(sub) for sub in chunk)
            embed = discord_common.cf_color_embed(description=hist_str)
            return title, embed

        pages = [
            make_page(chunk)
            for chunk in paginator.chunkify(submissions[:100], 10)
        ]
        paginator.paginate(self.bot,
                           ctx.channel,
                           pages,
                           wait_time=5 * 60,
                           set_pagenum_footers=True)
Esempio n. 6
0
    async def info(*, handles):
        chunks = chunkify(handles, MAX_HANDLES_PER_QUERY)
        if len(chunks) > 1:
            logger.warning(f'cf.info request with {len(handles)} handles,'
            f'will be chunkified into {len(chunks)} requests.')

        result = []
        for chunk in chunks:
            params = {'handles': ';'.join(chunk)}
            try:
                resp = await _query_api('user.info', params)
            except TrueApiError as e:
                if 'not found' in e.comment:
                    # Comment format is "handles: User with handle ***** not found"
                    handle = e.comment.partition('not found')[0].split()[-1]
                    raise HandleNotFoundError(e.comment, handle)
                raise
            result += [make_from_dict(User, user_dict) for user_dict in resp]
        return result