예제 #1
0
    async def gimme(self, ctx, *args):
        tags = []
        bounds = []
        for arg in args:
            if arg.isdigit():
                bounds.append(int(arg))
            else:
                tags.append(arg)

        handle, = await cf_common.resolve_handles(ctx, self.converter,
                                                  ('!' + str(ctx.author), ))
        user = cf_common.user_db.fetch_cfuser(handle)
        rating = user.rating
        submissions = await cf.user.status(handle=handle)
        solved = {
            sub.problem.name
            for sub in submissions if sub.verdict == 'OK'
        }

        lower = bounds[0] if len(bounds) > 0 else None
        if lower is None:
            lower = rating  # round later. rounding a null value causes exception
            if lower is None:
                await ctx.send(
                    'Personal cf data not found. Assume rating of 1500.')
                lower = 1500
            else:
                lower = round(lower, -2)
        upper = bounds[1] if len(bounds) > 1 else lower + 200
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if lower <= prob.rating and prob.name not in solved
        ]
        problems = [
            prob for prob in problems
            if not cf_common.is_contest_writer(prob.contestId, handle)
        ]
        if tags:
            problems = [prob for prob in problems if prob.tag_matches(tags)]
        if not problems:
            await ctx.send('Problems not found within the search parameters')
            return
        upper = max(upper, min([prob.rating for prob in problems]))
        problems = [prob for prob in problems if prob.rating <= upper]
        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choice = max([random.randrange(len(problems)) for _ in range(2)])
        problem = problems[choice]

        title = f'{problem.index}. {problem.name}'
        desc = cf_common.cache2.contest_cache.get_contest(
            problem.contestId).name
        embed = discord.Embed(title=title, url=problem.url, description=desc)
        embed.add_field(name='Rating', value=problem.rating)
        if tags:
            tagslist = ', '.join(problem.tag_matches(tags))
            embed.add_field(name='Matched tags', value=tagslist)
        await ctx.send(f'Recommended problem for `{handle}`', embed=embed)
예제 #2
0
 def get_problems(rating):
     return [
         prob for prob in cf_common.cache2.problem_cache.problems if
         prob.rating == rating and prob.name not in solved and not any(
             cf_common.is_contest_writer(prob.contestId, handle)
             for handle in handles)
         and not cf_common.is_nonstandard_problem(prob)
     ]
예제 #3
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)
예제 #4
0
    async def gimme(self, ctx, *args):
        handle, = await cf_common.resolve_handles(ctx, self.converter,
                                                  ('!' + str(ctx.author), ))
        rating = round(
            cf_common.user_db.fetch_cf_user(handle).effective_rating, -2)
        tags = []
        notags = []
        for arg in args:
            if arg.isdigit():
                rating = int(arg)
            else:
                if arg[0] == '-':
                    notags.append(arg[1:])
                else:
                    tags.append(arg)

        submissions = await cf.user.status(handle=handle)
        solved = {
            sub.problem.name
            for sub in submissions if sub.verdict == 'OK'
        }

        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if prob.rating == rating and prob.name not in solved
            and not cf_common.is_contest_writer(prob.contestId, handle)
        ]
        if tags:
            problems = [prob for prob in problems if prob.tag_matches(tags)]
        if notags:
            problems = [
                prob for prob in problems
                if (prob.tag_matches_or(notags) == None)
            ]

        if not problems:
            raise CodeforcesCogError(
                'Problems not found within the search parameters')

        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choice = max([random.randrange(len(problems)) for _ in range(2)])
        problem = problems[choice]

        title = f'{problem.index}. {problem.name}'
        desc = cf_common.cache2.contest_cache.get_contest(
            problem.contestId).name
        embed = discord.Embed(title=title, url=problem.url, description=desc)
        embed.add_field(name='Rating', value=problem.rating)
        if tags:
            tagslist = ', '.join(problem.tag_matches(tags))
            embed.add_field(name='Matched tags', value=tagslist)
        await ctx.send(f'Recommended problem for `{handle}`', embed=embed)
예제 #5
0
    async def gimme(self, ctx, *args):
        tags = []
        bounds = []
        for arg in args:
            if arg.isdigit():
                bounds.append(int(arg))
            else:
                tags.append(arg)

        (handle, ) = await cf_common.resolve_handles(ctx, self.converter,
                                                     ("!" + str(ctx.author), ))
        submissions = await cf.user.status(handle=handle)
        solved = {
            sub.problem.name
            for sub in submissions if sub.verdict == "OK"
        }

        lower = bounds[0] if len(bounds) > 0 else None
        if lower is None:
            user = cf_common.user_db.fetch_cf_user(handle)
            lower = round(user.effective_rating, -2)
        upper = bounds[1] if len(bounds) > 1 else lower + 200
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if lower <= prob.rating and prob.name not in solved
        ]
        problems = [
            prob for prob in problems
            if not cf_common.is_contest_writer(prob.contestId, handle)
        ]
        if tags:
            problems = [prob for prob in problems if prob.tag_matches(tags)]
        if not problems:
            await ctx.send("Problems not found within the search parameters")
            return
        upper = max(upper, min([prob.rating for prob in problems]))
        problems = [prob for prob in problems if prob.rating <= upper]
        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choice = max([random.randrange(len(problems)) for _ in range(2)])
        problem = problems[choice]

        title = f"{problem.index}. {problem.name}"
        desc = cf_common.cache2.contest_cache.get_contest(
            problem.contestId).name
        embed = discord.Embed(title=title, url=problem.url, description=desc)
        embed.add_field(name="Rating", value=problem.rating)
        if tags:
            tagslist = ", ".join(problem.tag_matches(tags))
            embed.add_field(name="Matched tags", value=tagslist)
        await ctx.send(f"Recommended problem for `{handle}`", embed=embed)
예제 #6
0
    async def mashup(self, ctx, *args):
        """Create a mashup contest using problems within +-100 of average rating of handles provided.
        Add tags with "+" before them.
        Ban tags with "~" before them.
        """
        handles = [arg for arg in args if arg[0] not in '+~']
        tags = cf_common.parse_tags(args, prefix='+')
        bantags = cf_common.parse_tags(args, prefix='~')

        handles = handles or ('!' + str(ctx.author), )
        handles = await cf_common.resolve_handles(ctx, self.converter, handles)
        resp = [await cf.user.status(handle=handle) for handle in handles]
        submissions = [sub for user in resp for sub in user]
        solved = {sub.problem.name for sub in submissions}
        info = await cf.user.info(handles=handles)
        rating = int(
            round(
                sum(user.effective_rating for user in info) / len(handles),
                -2))
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if abs(prob.rating -
                   rating) <= 100 and prob.name not in solved and not any(
                       cf_common.is_contest_writer(prob.contestId, handle)
                       for handle in handles)
            and not cf_common.is_nonstandard_problem(prob) and
            prob.matches_all_tags(tags) and not prob.matches_any_tag(bantags)
        ]

        if len(problems) < 4:
            raise CodeforcesCogError(
                'Problems not found within the search parameters')

        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choices = []
        for i in range(4):
            k = max(random.randrange(len(problems) - i) for _ in range(2))
            for c in choices:
                if k >= c:
                    k += 1
            choices.append(k)
            choices.sort()

        problems = reversed([problems[k] for k in choices])
        msg = '\n'.join(f'{"ABCD"[i]}: [{p.name}]({p.url}) [{p.rating}]'
                        for i, p in enumerate(problems))
        str_handles = '`, `'.join(handles)
        embed = discord_common.cf_color_embed(description=msg)
        await ctx.send(f'Mashup contest for `{str_handles}`', embed=embed)
예제 #7
0
    async def mashup(self, ctx, *args):
        """Create a mashup contest using problems within +-100 of average rating of handles provided.
        Add tags with "+" before them.
        """
        handles = [arg for arg in args if arg[0] != "+"]
        tags = [arg[1:] for arg in args if arg[0] == "+" and len(arg) > 1]

        handles = handles or ("!" + str(ctx.author), )
        handles = await cf_common.resolve_handles(ctx, self.converter, handles)
        resp = [await cf.user.status(handle=handle) for handle in handles]
        submissions = [sub for user in resp for sub in user]
        solved = {sub.problem.name for sub in submissions}
        info = await cf.user.info(handles=handles)
        rating = int(
            round(
                sum(user.effective_rating for user in info) / len(handles),
                -2))
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if abs(prob.rating -
                   rating) <= 100 and prob.name not in solved and not any(
                       cf_common.is_contest_writer(prob.contestId, handle)
                       for handle in handles)
            and not cf_common.is_nonstandard_problem(prob)
        ]
        if tags:
            problems = [prob for prob in problems if prob.tag_matches(tags)]

        if len(problems) < 4:
            await ctx.send("Problems not found within the search parameters")
            return

        problems = self._get_problems(problems)

        choices = []
        for i in range(4):
            k = max(random.randrange(len(problems) - i) for _ in range(2))
            for c in choices:
                if k >= c:
                    k += 1
            choices.append(k)
            choices.sort()

        problems = reversed([problems[k] for k in choices])
        msg = "\n".join(f'{"ABCD"[i]}: [{p.name}]({p.url}) [{p.rating}]'
                        for i, p in enumerate(problems))
        str_handles = "`, `".join(handles)
        embed = discord_common.cf_color_embed(description=msg)
        await ctx.send(f"Mashup contest for `{str_handles}`", embed=embed)
예제 #8
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[:5]
        ]
        msg = '\n'.join(f'{i+1}. [{c.name}]({c.url})'
                        for i, c in enumerate(contests))
        embed = discord_common.cf_color_embed(description=msg)
        str_handles = '`, `'.join(handles)
        await ctx.send(f'Recommended contest(s) for `{str_handles}`',
                       embed=embed)
예제 #9
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=10)
        user_submissions = [await cf.user.status(handle=handle) for handle in handles]
        info = await cf.user.info(handles=handles)
        contests = cf_common.cache2.contest_cache.get_contests_in_phase('FINISHED')
        problem_to_contests = cf_common.cache2.problemset_cache.problem_to_contests

        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
        for subs in user_submissions:
            for sub in subs:
                if sub.verdict == 'COMPILATION_ERROR':
                    continue

                try:
                    contest = cf_common.cache2.contest_cache.get_contest(sub.problem.contestId)
                    problem_id = (sub.problem.name, contest.startTimeSeconds)
                    for cid in problem_to_contests[problem_id]:
                        recommendations.discard(cid)
                except cache_system2.ContestNotFound:
                    pass

        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[:5]]
        msg = '\n'.join(f'{i+1}. [{c.name}]({c.url})' for i, c in enumerate(contests))
        embed = discord_common.cf_color_embed(description=msg)
        str_handles = '`, `'.join(handles)
        await ctx.send(f'Recommended contest(s) for `{str_handles}`', embed=embed)
예제 #10
0
    async def mashup(self, ctx, *handles: str):
        """Create a mashup contest using problems within +-100 of average rating of handles provided.
        """
        handles = handles or ('!' + str(ctx.author), )
        handles = await cf_common.resolve_handles(ctx, self.converter, handles)
        resp = [await cf.user.status(handle=handle) for handle in handles]
        submissions = [sub for user in resp for sub in user]
        solved = {sub.problem.name for sub in submissions}
        info = await cf.user.info(handles=handles)
        rating = int(
            round(
                sum(user.rating or 1500 for user in info) / len(handles), -2))
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if abs(prob.rating -
                   rating) <= 100 and prob.name not in solved and not any(
                       cf_common.is_contest_writer(prob.contestId, handle)
                       for handle in handles)
        ]

        if len(problems) < 4:
            await ctx.send('Problems not found within the search parameters')
            return

        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choices = []
        for i in range(4):
            k = max(random.randrange(len(problems) - i) for _ in range(2))
            for c in choices:
                if k >= c:
                    k += 1
            choices.append(k)
            choices.sort()

        problems = reversed([problems[k] for k in choices])
        msg = '\n'.join(f'{"ABCD"[i]}: [{p.name}]({p.url}) [{p.rating}]'
                        for i, p in enumerate(problems))
        str_handles = '`, `'.join(handles)
        embed = discord_common.cf_color_embed(description=msg)
        await ctx.send(f'Mashup contest for `{str_handles}`', embed=embed)
예제 #11
0
 def check(problem):
     return not cf_common.is_nonstandard_problem(
         problem) and not cf_common.is_contest_writer(
             problem.contestId, handle)
예제 #12
0
 def check(problem):
     contest = cf_common.cache2.contest_cache.get_contest(
         problem.contestId)
     return (not cf_common.is_nonstandard_contest(contest) and
             not cf_common.is_contest_writer(problem.contestId, handle))
예제 #13
0
    async def mashup(self, ctx, *args):
        """Create a mashup contest using problems within -200 and +400 of average rating of handles provided.
        Add tags with "+" before them.
        """
        delta = 100
        handles = [arg for arg in args if arg[0] != '+' and arg[0] != '?']
        tags = [arg[1:] for arg in args if arg[0] == '+' and len(arg) > 1]
        deltaStr = [arg[1:] for arg in args if arg[0] == '?' and len(arg) > 1]
        if len(deltaStr) > 1:
            raise CodeforcesCogError('Only one delta argument is allowed')
        if len(deltaStr) == 1:
            try:
                delta += round(int(deltaStr[0]), -2)
            except ValueError:
                raise CodeforcesCogError(
                    'delta could not be interpreted as number')

        handles = handles or ('!' + str(ctx.author), )
        handles = await cf_common.resolve_handles(ctx, self.converter, handles)
        resp = [await cf.user.status(handle=handle) for handle in handles]
        submissions = [sub for user in resp for sub in user]
        solved = {sub.problem.name for sub in submissions}
        info = await cf.user.info(handles=handles)
        rating = int(
            round(
                sum(user.effective_rating for user in info) / len(handles),
                -2))
        rating += delta
        rating = max(800, rating)
        rating = min(3500, rating)
        problems = [
            prob for prob in cf_common.cache2.problem_cache.problems
            if abs(prob.rating -
                   rating) <= 300 and prob.name not in solved and not any(
                       cf_common.is_contest_writer(prob.contestId, handle)
                       for handle in handles)
            and not cf_common.is_nonstandard_problem(prob)
        ]
        if tags:
            problems = [prob for prob in problems if prob.tag_matches(tags)]

        if len(problems) < 4:
            raise CodeforcesCogError(
                'Problems not found within the search parameters')

        problems.sort(key=lambda problem: cf_common.cache2.contest_cache.
                      get_contest(problem.contestId).startTimeSeconds)

        choices = []
        for i in range(4):
            k = max(random.randrange(len(problems) - i) for _ in range(2))
            for c in choices:
                if k >= c:
                    k += 1
            choices.append(k)
            choices.sort()

        problems = sorted([problems[k] for k in choices],
                          key=lambda problem: problem.rating)
        msg = '\n'.join(f'{"ABCD"[i]}: [{p.name}]({p.url}) [{p.rating}]'
                        for i, p in enumerate(problems))
        str_handles = '`, `'.join(handles)
        embed = discord_common.cf_color_embed(description=msg)
        await ctx.send(f'Mashup contest for `{str_handles}`', embed=embed)