def _plot_rating(plot_data, mark): for ratings, when in plot_data: plt.plot(when, ratings, linestyle='-', marker=mark, markersize=3, markerfacecolor='white', markeredgewidth=0.5) gc.plot_rating_bg(cf.RATED_RANKS)
async def vcperformance(self, ctx, *members: discord.Member): """Plots VC performance for at most 5 users.""" members = members or (ctx.author, ) if len(members) > 5: raise ContestCogError('Cannot plot more than 5 VCers at once.') plot_data = defaultdict(list) min_rating = 1100 max_rating = 1800 for member in members: rating_history = cf_common.user_db.get_vc_rating_history(member.id) if not rating_history: raise ContestCogError(f'{member.mention} has no vc history.') ratingbefore = 1500 for vc_id, rating in rating_history: vc = cf_common.user_db.get_rated_vc(vc_id) perf = ratingbefore + (rating - ratingbefore)*4 date = dt.datetime.fromtimestamp(vc.finish_time) plot_data[member.display_name].append((date, perf)) min_rating = min(min_rating, perf) max_rating = max(max_rating, perf) ratingbefore = rating plt.clf() # plot at least from mid gray to mid purple for rating_data in plot_data.values(): x, y = zip(*rating_data) plt.plot(x, y, linestyle='-', marker='o', markersize=4, markerfacecolor='white', markeredgewidth=0.5) gc.plot_rating_bg(cf.RATED_RANKS) plt.gcf().autofmt_xdate() plt.ylim(min_rating - 100, max_rating + 200) labels = [ gc.StrWrap('{} ({})'.format( member_display_name, ratingbefore)) for member_display_name, rating_data in plot_data.items() ] plt.legend(labels, loc='upper left', prop=gc.fontprop) discord_file = gc.get_current_figure_as_file() embed = discord_common.cf_color_embed(title='VC performance graph') discord_common.attach_image(embed, discord_file) discord_common.set_author_footer(embed, ctx.author) await ctx.send(embed=embed, file=discord_file)
def _plot_rating(resp, mark='o'): for rating_changes in resp: ratings, times = [], [] for rating_change in rating_changes: ratings.append(rating_change.newRating) times.append(dt.datetime.fromtimestamp(rating_change.ratingUpdateTimeSeconds)) plt.plot(times, ratings, linestyle='-', marker=mark, markersize=3, markerfacecolor='white', markeredgewidth=0.5) gc.plot_rating_bg(cf.RATED_RANKS) plt.gcf().autofmt_xdate()
def _plot_rating(resp, mark='o', labels: List[str] = None): labels = [''] * len(resp) if labels is None else labels for rating_changes, label in zip(resp, labels): ratings, times = [], [] for rating_change in rating_changes: ratings.append(rating_change.newRating) times.append(dt.datetime.fromtimestamp(rating_change.ratingUpdateTimeSeconds)) plt.plot(times, ratings, linestyle='-', marker=mark, markersize=3, markerfacecolor='white', markeredgewidth=0.5, label=label) gc.plot_rating_bg(cf.RATED_RANKS) plt.gcf().autofmt_xdate()
def _plot_extreme(handle, rating, packed_contest_subs_problemset, solved, unsolved): extremes = [ (dt.datetime.fromtimestamp(contest.end_time), _get_extremes(contest, problemset, subs)) for contest, problemset, subs in packed_contest_subs_problemset ] regular = [] fullsolves = [] nosolves = [] for t, (mn, mx) in extremes: if mn and mx: regular.append((t, mn, mx)) elif mx: fullsolves.append((t, mx)) elif mn: nosolves.append((t, mn)) else: # No rated problems in the contest, which means rating is not yet available for # problems in this contest. Skip this data point. pass solvedcolor = 'tab:orange' unsolvedcolor = 'tab:blue' linecolor = '#00000022' outlinecolor = '#00000022' def scatter_outline(*args, **kwargs): plt.scatter(*args, **kwargs) kwargs['zorder'] -= 1 kwargs['color'] = outlinecolor if kwargs['marker'] == '*': kwargs['s'] *= 3 elif kwargs['marker'] == 's': kwargs['s'] *= 1.5 else: kwargs['s'] *= 2 if 'alpha' in kwargs: del kwargs['alpha'] if 'label' in kwargs: del kwargs['label'] plt.scatter(*args, **kwargs) plt.clf() time_scatter, plot_min, plot_max = zip(*regular) if unsolved: scatter_outline(time_scatter, plot_min, zorder=10, s=14, marker='o', color=unsolvedcolor, label='Easiest unsolved') if solved: scatter_outline(time_scatter, plot_max, zorder=10, s=14, marker='o', color=solvedcolor, label='Hardest solved') ax = plt.gca() if solved and unsolved: for t, mn, mx in regular: ax.add_line(mlines.Line2D((t, t), (mn, mx), color=linecolor)) if fullsolves: scatter_outline(*zip(*fullsolves), zorder=15, s=42, marker='*', color=solvedcolor) if nosolves: scatter_outline(*zip(*nosolves), zorder=15, s=32, marker='X', color=unsolvedcolor) plt.legend(title=f'{handle}: {rating}', title_fontsize=plt.rcParams['legend.fontsize'], loc='upper left').set_zorder(20) gc.plot_rating_bg(cf.RATED_RANKS) plt.gcf().autofmt_xdate()
async def rating(self, ctx, *members: discord.Member): """Plot duelist's rating.""" members = members or (ctx.author, ) if len(members) > 5: raise DuelCogError(f'Cannot plot more than 5 duelists at once.') duelists = [member.id for member in members] duels = cf_common.user_db.get_complete_official_duels() rating = dict() plot_data = defaultdict(list) time_tick = 0 for challenger, challengee, winner, finish_time in duels: challenger_r = rating.get(challenger, 1500) challengee_r = rating.get(challengee, 1500) if winner == Winner.CHALLENGER: delta = round(elo_delta(challenger_r, challengee_r, 1)) elif winner == Winner.CHALLENGEE: delta = round(elo_delta(challenger_r, challengee_r, 0)) else: delta = round(elo_delta(challenger_r, challengee_r, 0.5)) rating[challenger] = challenger_r + delta rating[challengee] = challengee_r - delta if challenger in duelists or challengee in duelists: if challenger in duelists: plot_data[challenger].append( (time_tick, rating[challenger])) if challengee in duelists: plot_data[challengee].append( (time_tick, rating[challengee])) time_tick += 1 if time_tick == 0: raise DuelCogError(f'Nothing to plot.') plt.clf() # plot at least from mid gray to mid purple min_rating = 1350 max_rating = 1550 for rating_data in plot_data.values(): for tick, rating in rating_data: min_rating = min(min_rating, rating) max_rating = max(max_rating, rating) x, y = zip(*rating_data) plt.plot(x, y, linestyle='-', marker='o', markersize=2, markerfacecolor='white', markeredgewidth=0.5) gc.plot_rating_bg(DUEL_RANKS) plt.xlim(0, time_tick - 1) plt.ylim(min_rating - 100, max_rating + 100) labels = [ gc.StrWrap('{} ({})'.format( ctx.guild.get_member(duelist).display_name, rating_data[-1][1])) for duelist, rating_data in plot_data.items() ] plt.legend(labels, loc='upper left', prop=gc.fontprop) discord_file = gc.get_current_figure_as_file() embed = discord_common.cf_color_embed(title='Duel rating graph') discord_common.attach_image(embed, discord_file) discord_common.set_author_footer(embed, ctx.author) await ctx.send(embed=embed, file=discord_file)
def _plot_extreme(handle, rating, packed_contest_subs_problemset, solved, unsolved): extremes = [( dt.datetime.fromtimestamp(contest.end_time), _get_extremes(contest, problemset, subs), ) for contest, problemset, subs in packed_contest_subs_problemset] regular = [] fullsolves = [] nosolves = [] for t, (mn, mx) in extremes: if mn and mx: regular.append((t, mn, mx)) elif mx: fullsolves.append((t, mx)) elif mn: nosolves.append((t, mn)) else: # No rated problems in the contest, which means rating is not yet available for # problems in this contest. Skip this data point. pass solvedcolor = "tab:orange" unsolvedcolor = "tab:blue" linecolor = "#00000022" outlinecolor = "#00000022" def scatter_outline(*args, **kwargs): plt.scatter(*args, **kwargs) kwargs["zorder"] -= 1 kwargs["color"] = outlinecolor if kwargs["marker"] == "*": kwargs["s"] *= 3 elif kwargs["marker"] == "s": kwargs["s"] *= 1.5 else: kwargs["s"] *= 2 if "alpha" in kwargs: del kwargs["alpha"] if "label" in kwargs: del kwargs["label"] plt.scatter(*args, **kwargs) plt.clf() time_scatter, plot_min, plot_max = zip(*regular) if unsolved: scatter_outline( time_scatter, plot_min, zorder=10, s=14, marker="o", color=unsolvedcolor, label="Easiest unsolved", ) if solved: scatter_outline( time_scatter, plot_max, zorder=10, s=14, marker="o", color=solvedcolor, label="Hardest solved", ) ax = plt.gca() if solved and unsolved: for t, mn, mx in regular: ax.add_line(mlines.Line2D((t, t), (mn, mx), color=linecolor)) if fullsolves: scatter_outline(*zip(*fullsolves), zorder=15, s=42, marker="*", color=solvedcolor) if nosolves: scatter_outline(*zip(*nosolves), zorder=15, s=32, marker="X", color=unsolvedcolor) plt.legend( title=f"{handle}: {rating}", title_fontsize=plt.rcParams["legend.fontsize"], loc="upper left", ).set_zorder(20) gc.plot_rating_bg(cf.RATED_RANKS) plt.gcf().autofmt_xdate()