Exemplo n.º 1
0
async def rating(ctx):
    """Plot rating progression"""
    peak = ctx.options.peak
    usernames = ctx.options.usernames

    query = Query()
    if usernames == []:
        usernames = [query.get_handle(ctx.author.id, ctx.get_guild().id)]

    try:
        users = await asyncio.gather(*[query.get_user(username) for username in usernames])
    except ObjectNotFound:
        return await ctx.respond("User not found")

    usernames = [user.username for user in users]
    for i in range(len(users)):
        if users[i] is None:
            return await ctx.respond(f"{usernames[i]} does not exist on DMOJ")
    if len(users) > 10:
        return await ctx.respond("Too many users given, max 10")

    cond = [Contest_DB.rankings.contains(user.username) for user in users]
    q = session.query(Contest_DB).filter(or_(*cond)).filter(Contest_DB.is_rated == 1)
    contests = q.all()

    def get_rating_change(rankings, users):
        ret = {}
        for ranking in rankings:
            for user in users:
                if user.username == ranking["user"] and ranking["new_rating"]:
                    ret[user.username] = ranking["new_rating"]
        return ret

    data = {}
    data["users"] = [user.username for user in users]
    userPrevRating = {}
    for contest in contests:
        changes = get_rating_change(contest.rankings, users)
        data[contest.end_time] = []
        for user in users:
            if user.username in changes and (
                not peak or changes[user.username] >= userPrevRating.get(user.username, -9999)
            ):
                change = changes[user.username]
                userPrevRating[user.username] = change
                data[contest.end_time].append(change)
            else:
                data[contest.end_time].append(None)
    plot_rating(data)

    embed = hikari.Embed(
        title="Rating Progression",
        color=0xFCDB05,
    )
    with open("./graphs/plot.png", "rb") as file:
        embed.set_image(hikari.Bytes(file.read(), "plot.png"))

    return await ctx.respond(embed=embed)
Exemplo n.º 2
0
    async def rating(self,
                     ctx,
                     peak: typing.Optional[plot_peak] = False,
                     *usernames):
        """Plot rating progression"""
        usernames = list(usernames)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        users = await asyncio.gather(
            *[query.get_user(username) for username in usernames])
        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        cond = [Contest_DB.rankings.contains(user.username) for user in users]
        q = session.query(Contest_DB).filter(or_(*cond))\
            .filter(Contest_DB.is_rated == 1)
        contests = q.all()

        def get_rating_change(rankings, users):
            ret = {}
            for ranking in rankings:
                for user in users:
                    if (user.username == ranking['user']
                            and ranking['new_rating']):
                        ret[user.username] = ranking['new_rating']
            return ret

        data = {}
        data['users'] = [user.username for user in users]
        userPrevRating = {}
        for contest in contests:
            changes = get_rating_change(contest.rankings, users)
            data[contest.end_time] = []
            for user in users:
                if user.username in changes \
                        and (not peak or changes[user.username] >= userPrevRating.get(user.username, -9999)):
                    change = changes[user.username]
                    userPrevRating[user.username] = change
                    data[contest.end_time].append(change)
                else:
                    data[contest.end_time].append(None)
        plot_rating(data)
        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Contest Rating',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 3
0
    async def solved(self, ctx, *usernames):
        """Plot problems solved over time"""
        usernames = list(usernames)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        users = await asyncio.gather(
            *[query.get_user(username) for username in usernames])
        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        total_data = {}
        not_cached = []
        for username in usernames:
            q = session.query(Submission_DB)\
                .filter(Submission_DB._user == username)
            if q.count() == 0:
                not_cached.append(username)

            q = session.query(func.min(Submission_DB.date))\
                .join(Problem_DB, Problem_DB.code == Submission_DB._code)\
                .filter(Submission_DB._user == username)\
                .filter(Submission_DB.points == Problem_DB.points)\
                .group_by(Submission_DB._code)
            dates = list(map(first_tuple, q.all()))
            dates.sort()
            data_to_plot = {}
            cnt = 0
            for date in dates:
                cnt += 1
                data_to_plot[date] = cnt
            total_data[username] = data_to_plot

        plot_solved(total_data)

        if len(not_cached):
            await ctx.send(f"`{', '.join(not_cached)} do not have any cached "
                           f"submissions. Please use +cache [username]`")

        plot_points(total_data)

        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Problems Solved',
            color=0xfcdb05,
        )
        embed.set_image(url=f'attachment://plot.png', )

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 4
0
async def solved(ctx):
    """Plot problems solved over time"""
    usernames = ctx.options.usernames

    query = Query()
    if usernames == []:
        usernames = [query.get_handle(ctx.author.id, ctx.get_guild().id)]

    try:
        users = await asyncio.gather(*[query.get_user(username) for username in usernames])
    except ObjectNotFound:
        return await ctx.respond("User not found")

    usernames = [user.username for user in users]
    for i in range(len(users)):
        if users[i] is None:
            return await ctx.respond(f"{usernames[i]} does not exist on DMOJ")
    if len(users) > 10:
        return await ctx.respond("Too many users given, max 10")

    total_data = {}
    for username in usernames:
        q = session.query(Submission_DB).filter(Submission_DB._user == username)
        if q.count() == 0:
            await ctx.respond(f"`{username}` does not have any cached submissions, caching now")
            await query.get_submissions(username)

        q = (
            session.query(func.min(Submission_DB.date))
            .join(Problem_DB, Problem_DB.code == Submission_DB._code)
            .filter(Submission_DB._user == username)
            .filter(Submission_DB.points == Problem_DB.points)
            .group_by(Submission_DB._code)
        )
        dates = list(map(itemgetter(0), q.all()))
        dates.sort()
        data_to_plot = {}
        cnt = 0
        for date in dates:
            cnt += 1
            data_to_plot[date] = cnt
        total_data[username] = data_to_plot

    plot_solved(total_data)

    embed = hikari.Embed(
        title="Problems Solved",
        color=0xFCDB05,
    )
    with open("./graphs/plot.png", "rb") as file:
        embed.set_image(hikari.Bytes(file.read(), "plot.png"))

    return await ctx.respond(embed=embed)
Exemplo n.º 5
0
    async def vc(self, ctx, *usernames):
        """Suggest a contest"""
        usernames = list(usernames)

        query = Query()
        if usernames == []:
            username = query.get_handle(ctx.author.id, ctx.guild.id)
            if username:
                usernames = [username]

        users = await asyncio.gather(*[query.get_user(username)
                                     for username in usernames])
        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')

        q = session.query(Contest_DB)
        for user in users:
            # if the user has attempted any problems from the problem set
            sub_q = session.query(Submission_DB,
                                  func.max(Submission_DB.points))\
                .filter(Submission_DB._user == user.username)\
                .group_by(Submission_DB._code).subquery()
            sub_q = session.query(Problem_DB.code)\
                .join(sub_q, Problem_DB.code == sub_q.c._code, isouter=True)\
                .filter(func.ifnull(sub_q.c.points, 0) != 0)
            sub_q = list(map(itemgetter(0), sub_q.all()))
            q = q.filter(not_(Contest_DB.rankings.contains(user.username)))\
                .filter(~Contest_DB.problems.any(Problem_DB.code.in_(sub_q)))

        if q.count() == 0:
            await ctx.send("Cannot find any contests which "
                           "all users have not done")
            return
        contest = random.choice(q.all())

        # When problems are private, it says there are no problems
        window = 'No'
        is_rated = 'Not Rated'
        if contest.time_limit:
            window = f"{contest.time_limit/60/60} Hr"
        if contest.is_rated:
            is_rated = "Rated"
        embed = discord.Embed(
            title=contest.name, url=f"https://dmoj.ca/contest/{contest.key}",
            description=f"{window} window | {len(contest.problems)} Problems | {is_rated}",
            color=0xfcdb05
        )
        await ctx.send(embed=embed)
Exemplo n.º 6
0
async def vc(ctx):
    usernames = ctx.options.usernames
    print(usernames)
    query = Query()
    if usernames == []:
        username = query.get_handle(ctx.author.id, ctx.get_guild().id)
        if username:
            usernames = [username]

    users = await asyncio.gather(
        *[query.get_user(username) for username in usernames])
    usernames = [user.username for user in users]
    for i in range(len(users)):
        if users[i] is None:
            return await ctx.respond(f"{usernames[i]} does not exist on DMOJ")

    q = session.query(Contest_DB)
    for user in users:
        # if the user has attempted any problems from the problem set
        sub_q = (session.query(Submission_DB, func.max(
            Submission_DB.points)).filter(
                Submission_DB._user == user.username).group_by(
                    Submission_DB._code).subquery())
        sub_q = (session.query(Problem_DB.code).join(
            sub_q, Problem_DB.code == sub_q.c._code,
            isouter=True).filter(func.ifnull(sub_q.c.points, 0) != 0))
        sub_q = list(map(itemgetter(0), sub_q.all()))
        q = (q.filter(not_(Contest_DB.rankings.contains(
            user.username))).filter(
                ~Contest_DB.problems.any(Problem_DB.code.in_(sub_q))).filter(
                    Contest_DB.is_private == 0).filter(
                        Contest_DB.is_organization_private == 0))

    if q.count() == 0:
        await ctx.respond("Cannot find any contests which "
                          "all users have not done")
        return

    contests = q.all()

    while True:
        contest = random.choice(contests)
        try:
            contest = await query.get_contest(contest.key, cached=False)
            break
        except ObjectNotFound:
            pass

    # When problems are private, it says there are no problems
    window = "No"
    is_rated = "Not Rated"
    if contest.time_limit:
        window = f"{round(contest.time_limit/60/60, 2)} Hr"
    if contest.is_rated:
        is_rated = "Rated"
    embed = hikari.Embed(
        title=contest.name,
        url=f"https://dmoj.ca/contest/{contest.key}",
        description=
        f"{window} window | {len(contest.problems)} Problems | {is_rated}",
        color=0xFCDB05,
    )
    await ctx.respond(embed=embed)
Exemplo n.º 7
0
    async def type(self,
                   ctx,
                   as_percent: typing.Optional[as_percentage] = True,
                   graph: typing.Optional[graph_type] = 'radar',
                   *usernames):
        """Graph problems solved by popular problem types"""
        # This is aids, pls fix

        usernames = list(usernames)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        users = await asyncio.gather(
            *[query.get_user(username) for username in usernames])
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')

        if len(users) > 6:
            return await ctx.send('Too many users given, max 6')

        usernames = [data.username for data in users]

        important_types = [['Data Structures'], ['Dynamic Programming'],
                           ['Graph Theory'], ['String Algorithms'],
                           [
                               'Advanced Math', 'Geometry',
                               'Intermediate Math', 'Simple Math'
                           ], ['Ad Hoc'], ['Greedy Algorithms']]
        labels = [
            'Data Structures', 'Dynamic Programming', 'Graph Theory',
            'String Algorithms', 'Math', 'Ad Hoc', 'Greedy Algorithms'
        ]

        data = {}
        data['group'] = []
        for label in labels:
            data[label] = []
        for username in usernames:
            data['group'].append(username)

        def calculate_points(points: int):
            p = 0
            for i in range(min(100, len(points))):
                p += (0.95**i) * points[i]
            return p

        def to_points(problem):
            return problem.points

        max_percentage = 0
        not_cached = []

        for username in usernames:
            q = session.query(Submission_DB)\
                .filter(Submission_DB._user == username)
            if q.count() == 0:
                not_cached.append(username)

        for i, types in enumerate(important_types):
            total_problems = await query.get_problems(_type=types, cached=True)
            total_points = list(map(to_points, total_problems))
            total_points.sort(reverse=True)
            total_points = calculate_points(total_points)

            for username in usernames:
                problems = query.get_attempted_problems(username, types)

                points = list(map(to_points, problems))
                points.sort(reverse=True)

                points = calculate_points(points)
                if as_percent:
                    percentage = 100 * points / total_points
                else:
                    percentage = points
                max_percentage = max(max_percentage, percentage)
                data[labels[i]].append(percentage)

        print(data)
        if len(not_cached):
            await ctx.send(f"`{', '.join(not_cached)} do not have any cached "
                           f"submissions. Please use +cache [username]`")

        if graph == 'radar':
            plot_type_radar(data, as_percent, max_percentage)
        elif graph == 'bar':
            plot_type_bar(data, as_percent)

        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Problem types solved',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 8
0
    async def points(self, ctx, *usernames):
        """Plot point progression"""
        usernames = list(usernames)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        users = await asyncio.gather(
            *[query.get_user(username) for username in usernames])
        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        total_data = {}
        not_cached = []
        for username in usernames:
            q = session.query(Submission_DB)\
                .options(orm.joinedload('problem'))\
                .join(User_DB, User_DB.username == Submission_DB._user,
                      aliased=True)\
                .filter(User_DB.username == username)\
                .order_by(Submission_DB.date)

            def calculate_points(points, fully_solved):
                b = 150 * (1 - 0.997**fully_solved)
                p = 0
                for i in range(min(100, len(points))):
                    p += (0.95**i) * points[i]
                return b + p

            submissions = q.all()
            if len(submissions) == 0:
                not_cached.append(username)
            problems_ACed = dict()
            code_to_points = dict()

            points_arr = []
            data_to_plot = {}
            # O(N^2logN) :blobcreep:
            for submission in submissions:
                code = submission.problem[0].code
                points = submission.points
                result = submission.result

                if points is not None:
                    if result == 'AC':
                        problems_ACed[code] = 1
                    if code not in code_to_points:
                        # log N search, N insert
                        code_to_points[code] = points
                        bisect.insort(points_arr, points)
                    elif points > code_to_points[code]:
                        # N remove, log N search, N insert
                        points_arr.remove(code_to_points[code])
                        code_to_points[code] = points
                        bisect.insort(points_arr, points)
                    cur_points = calculate_points(points_arr[::-1],
                                                  len(problems_ACed))
                    data_to_plot[submission.date] = cur_points
            total_data[username] = data_to_plot

        if len(not_cached):
            await ctx.send(f"`{', '.join(not_cached)} do not have any cached "
                           f"submissions. Please use +cache [username]`")

        plot_points(total_data)

        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Point Progression',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 9
0
async def type(ctx):
    """Graph problems solved by popular problem types"""
    # TODO: This is aids, pls fix

    usernames = ctx.options.usernames
    graph_type = ctx.options.graph_type
    as_percent = ctx.options.as_percent

    query = Query()
    if usernames == []:
        usernames = [query.get_handle(ctx.author.id, ctx.get_guild().id)]

    try:
        users = await asyncio.gather(*[query.get_user(username) for username in usernames])
    except ObjectNotFound:
        return await ctx.respond("User not found")

    for i in range(len(users)):
        if users[i] is None:
            return await ctx.respond(f"{usernames[i]} does not exist on DMOJ")

    if len(users) > 6:
        return await ctx.respond("Too many users given, max 6")

    usernames = [data.username for data in users]

    important_types = [
        ["Data Structures"],
        ["Dynamic Programming"],
        ["Graph Theory"],
        ["String Algorithms"],
        ["Advanced Math", "Geometry", "Intermediate Math", "Simple Math"],
        ["Ad Hoc"],
        ["Greedy Algorithms"],
    ]
    labels = [
        "Data Structures",
        "Dynamic Programming",
        "Graph Theory",
        "String Algorithms",
        "Math",
        "Ad Hoc",
        "Greedy Algorithms",
    ]

    data = {}
    data["group"] = []
    for label in labels:
        data[label] = []
    for username in usernames:
        data["group"].append(username)

    def calculate_partial_points(points: int):
        p = 0
        for i in range(min(100, len(points))):
            p += (0.95**i) * points[i]
        return p

    max_percentage = 0

    for username in usernames:
        q = session.query(Submission_DB).filter(Submission_DB._user == username)
        if q.count() == 0:
            await ctx.respond(f"`{username}` does not have any cached submissions, caching now")
            await query.get_submissions(username)

    for i, types in enumerate(important_types):
        total_problems = await query.get_problems(_type=types, cached=True)
        total_points = list(map(attrgetter("points"), total_problems))
        total_points.sort(reverse=True)
        total_points = calculate_partial_points(total_points)

        for username in usernames:
            points = query.get_attempted_problems(username, types)

            points.sort(reverse=True)

            points = calculate_partial_points(points)
            if as_percent:
                percentage = 100 * points / total_points
            else:
                percentage = points
            max_percentage = max(max_percentage, percentage)
            data[labels[i]].append(percentage)

    logger.debug("plot type data: %s", data)

    if graph_type == "radar":
        plot_type_radar(data, as_percent, max_percentage)
    elif graph_type == "bar":
        plot_type_bar(data, as_percent)

    embed = hikari.Embed(
        title="Problem types solved",
        color=0xFCDB05,
    )
    with open("./graphs/plot.png", "rb") as file:
        embed.set_image(hikari.Bytes(file.read(), "plot.png"))

    return await ctx.respond(embed=embed)
Exemplo n.º 10
0
async def points(ctx):
    """Plot point progression"""
    usernames = ctx.options.usernames

    query = Query()
    if usernames == []:
        usernames = [query.get_handle(ctx.author.id, ctx.get_guild().id)]

    try:
        users = await asyncio.gather(*[query.get_user(username) for username in usernames])
    except ObjectNotFound:
        return await ctx.respond("User not found")

    usernames = [user.username for user in users]
    for i in range(len(users)):
        if users[i] is None:
            return await ctx.respond(f"{usernames[i]} does not exist on DMOJ")
    if len(users) > 10:
        return await ctx.respond("Too many users given, max 10")

    total_data = {}
    for username in usernames:
        q = (
            session.query(Submission_DB)
            .options(orm.joinedload("problem"))
            .join(User_DB, User_DB.username == Submission_DB._user, aliased=True)
            .filter(User_DB.username == username)
            .order_by(Submission_DB.date)
        )

        submissions = q.all()
        if len(submissions) == 0:
            await ctx.respond(f"`{username}` does not have any cached submissions, caching now")
            await query.get_submissions(username)
            submissions = q.all()
        problems_ACed = dict()
        code_to_points = dict()

        points_arr = []
        data_to_plot = {}
        # O(N^2logN) :blobcreep:
        for submission in submissions:
            code = submission.problem[0].code
            points = submission.points
            result = submission.result

            if points is not None:
                if result == "AC":
                    problems_ACed[code] = 1
                if code not in code_to_points:
                    # log N search, N insert
                    code_to_points[code] = points
                    bisect.insort(points_arr, points)
                elif points > code_to_points[code]:
                    # N remove, log N search, N insert
                    points_arr.remove(code_to_points[code])
                    code_to_points[code] = points
                    bisect.insort(points_arr, points)
                cur_points = calculate_points(points_arr[::-1], len(problems_ACed))
                data_to_plot[submission.date] = cur_points
        total_data[username] = data_to_plot

    plot_points(total_data)

    embed = hikari.Embed(
        title="Problems Progression",
        color=0xFCDB05,
    )
    with open("./graphs/plot.png", "rb") as file:
        embed.set_image(hikari.Bytes(file.read(), "plot.png"))

    return await ctx.respond(embed=embed)
Exemplo n.º 11
0
    async def solved(self, ctx, *args):
        '''Plot problems solved over time'''
        usernames = []
        minDate = datetime.min
        maxDate = datetime.max
        for arg in args:
            if arg.startswith('d>='):
                minDate = arg[3:]
                minDate = datetime(int(minDate[4:]), int(minDate[2:4]),
                                   int(minDate[0:2]))
            elif arg.startswith('d<='):
                maxDate = arg[3:]
                maxDate = datetime(int(maxDate[4:]), int(maxDate[2:4]),
                                   int(maxDate[0:2]))
            else:
                usernames.append(arg)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        try:
            users = await asyncio.gather(
                *[query.get_user(username) for username in usernames])
        except ObjectNotFound:
            return await ctx.send('User not found')

        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        total_data = {}
        for username in usernames:
            await query.get_submissions(username)
            q = session.query(Submission_DB)\
                .filter(Submission_DB._user == username)
            if q.count() == 0:
                await ctx.send(
                    f'`{username}` does not have any cached submissions, caching now'
                )
                await query.get_submissions(username)

            q = session.query(func.min(Submission_DB.date))\
                .join(Problem_DB, Problem_DB.code == Submission_DB._code)\
                .filter(Submission_DB._user == username)\
                .filter(Submission_DB.points == Problem_DB.points)\
                .group_by(Submission_DB._code)
            dates = list(map(itemgetter(0), q.all()))
            dates.sort()
            data_to_plot = {}
            cnt = 0
            for date in dates:
                if minDate <= date and date <= maxDate:
                    cnt += 1
                    data_to_plot[date] = cnt
            total_data[username] = data_to_plot

        plot_solved(total_data)

        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Problems Solved',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 12
0
    async def rating(self, ctx, *args, perf=False):
        '''Plot rating progression'''
        usernames = []
        peak = False
        raw = False
        for arg in args:
            if arg in ['+peak', '+max']:
                peak = True
            elif arg == '+raw':
                raw = True
            elif arg == '+perf':
                perf = True
            else:
                usernames.append(arg)
        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        try:
            users = await asyncio.gather(
                *[query.get_user(username) for username in usernames])
        except ObjectNotFound:
            return await ctx.send('User not found')

        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        cond = [Contest_DB.rankings.contains(user.username) for user in users]
        q = session.query(Contest_DB).filter(or_(*cond))\
            .filter(Contest_DB.is_rated == 1)
        contests = q.all()

        ratingVals = {}
        for (i, user) in enumerate(users):
            prevMax = -1e9
            for contest in user._contests:
                val = 0
                if perf:
                    val = contest['performance']
                elif raw:
                    val = contest['raw_rating']
                else:
                    val = contest['rating']
                if not peak or val and prevMax < val:
                    prevMax = val
                    ratingVals[contest['key'] + '.' + user.username] = val

        data = {}
        data['users'] = [user.username for user in users]

        for contest in contests:
            data[contest.end_time] = []
            for user in users:
                if contest.key + '.' + user.username in ratingVals:
                    data[contest.end_time].append(
                        ratingVals[contest.key + '.' + user.username])
                else:
                    data[contest.end_time].append(None)
        plot_rating(data)
        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Contest Rating',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)
Exemplo n.º 13
0
    async def points(self, ctx, *usernames):
        '''Plot point progression'''
        usernames = list(usernames)

        query = Query()
        if usernames == []:
            usernames = [query.get_handle(ctx.author.id, ctx.guild.id)]

        try:
            users = await asyncio.gather(
                *[query.get_user(username) for username in usernames])
        except ObjectNotFound:
            return await ctx.send('User not found')

        usernames = [user.username for user in users]
        for i in range(len(users)):
            if users[i] is None:
                return await ctx.send(f'{usernames[i]} does not exist on DMOJ')
        if len(users) > 10:
            return await ctx.send('Too many users given, max 10')

        total_data = {}
        for username in usernames:
            await query.get_submissions(username)
            q = session.query(Submission_DB)\
                .options(orm.joinedload('problem'))\
                .join(User_DB, User_DB.username == Submission_DB._user,
                      aliased=True)\
                .filter(User_DB.username == username)\
                .order_by(Submission_DB.date)

            submissions = q.all()
            if len(submissions) == 0:
                await ctx.send(
                    f'`{username}` does not have any cached submissions, caching now'
                )
                await query.get_submissions(username)
                submissions = q.all()
            problems_ACed = dict()
            code_to_points = dict()

            points_arr = []
            data_to_plot = {}
            # O(N^2logN) :blobcreep:
            for submission in submissions:
                code = submission.problem[0].code
                points = submission.points
                result = submission.result

                if points is not None:
                    if result == 'AC':
                        problems_ACed[code] = 1
                    if code not in code_to_points:
                        # log N search, N insert
                        code_to_points[code] = points
                        bisect.insort(points_arr, points)
                    elif points > code_to_points[code]:
                        # N remove, log N search, N insert
                        points_arr.remove(code_to_points[code])
                        code_to_points[code] = points
                        bisect.insort(points_arr, points)
                    cur_points = calculate_points(points_arr[::-1],
                                                  len(problems_ACed))
                    data_to_plot[submission.date] = cur_points
            total_data[username] = data_to_plot

        plot_points(total_data)

        with open('./graphs/plot.png', 'rb') as file:
            file = discord.File(io.BytesIO(file.read()), filename='plot.png')
        embed = discord.Embed(
            title='Point Progression',
            color=0xfcdb05,
        )
        embed.set_image(url='attachment://plot.png')

        return await ctx.send(embed=embed, file=file)