Exemple #1
0
async def stat_score(bot: NoneBot, ctx: Context_T, args: ParseResult):
    bm = BattleMaster(ctx['group_id'])
    now = datetime.now()
    clan = _check_clan(bm)
    yyyy, mm, _ = bm.get_yyyymmdd(now)
    stat = bm.stat_score(1, now)
    stat.sort(key=lambda x: x[3], reverse=True)

    if not len(stat):
        await bot.send(ctx,
                       f"{clan['name']}{yyyy}年{mm}月会战统计数据为空",
                       at_sender=True)
        return

    # msg = [ f"\n{yyyy}年{mm}月会战{clan['name']}分数统计:" ]
    # for _, _, name, score in stat:
    #     score = f'{score:,d}'           # 数字太多会被腾讯ban,用逗号分隔
    #     blank = '  ' * (11-len(score))  # QQ字体非等宽,width(空格*2) == width(数字*1)
    #     msg.append(f"{blank}{score}分 | {name}")

    # generate statistic figure
    fig, ax = plt.subplots()
    score = list(map(lambda i: i[3], stat))
    yn = len(stat)
    name = list(map(lambda i: i[2], stat))
    y_pos = list(range(yn))

    if score[0] >= 1e8:
        unit = 1e8
        unit_str = 'e'
    else:
        unit = 1e4
        unit_str = 'w'

    y_size = 0.3 * yn + 1.0
    fig.set_size_inches(10, y_size)
    bars = ax.barh(y_pos, score, align='center')
    ax.set_title(f"{clan['name']}{yyyy}年{mm}月会战分数统计")
    ax.set_yticks(y_pos)
    ax.set_yticklabels(name)
    ax.set_ylim((-0.6, yn - 0.4))
    ax.invert_yaxis()
    ax.set_xlabel('分数')
    ax.ticklabel_format(axis='x', style='plain')
    for rect in bars:
        w = rect.get_width()
        ax.text(w,
                rect.get_y() + rect.get_height() / 2,
                f'{w/unit:.2f}{unit_str}',
                ha='left',
                va='center')
    plt.subplots_adjust(left=0.12,
                        right=0.96,
                        top=1 - 0.35 / y_size,
                        bottom=0.55 / y_size)
    pic = util.fig2b64(plt)
    plt.close()

    msg = f"{ms.image(pic)}\n※伤害统计请发送“!伤害统计”"
    await bot.send(ctx, msg, at_sender=True)
async def send_time_dist(bot, event):
    gid = event['group_id']
    year, month = get_ym()

    try:
        name, times = get_time(gid, year, month)
    except Exception as e:
        await bot.send(event, f"出现错误: {str(e)}\n请联系开发组调教。")
        return

    plt.rcParams['axes.unicode_minus'] = False
    prop = fm.FontProperties(fname=font_path)
    prop.set_size('large')
    fig, ax = plt.subplots(figsize=(12, 6), facecolor='white')
    ax.set_xlabel('时间', fontproperties=prop)
    ax.set_ylabel('刀数', fontproperties=prop)
    ax.set_title(f'{name}{year}年{month}月会战出刀时间统计', fontproperties=prop)
    ax.set_xlim((0 - 0.5, 24))
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    colors = (['#808080'] * 6) + (['#9bc5af'] * 6) + (['#c54731'] *
                                                      6) + (['#3a4a59'] * 6)

    labels = list(range(5, 24)) + list(range(5))
    labels = [str(s) for s in labels]
    plt.xticks(range(24), labels, fontproperties=prop)
    plt.bar(range(24), times, color=colors)

    pic = fig2b64(plt)
    plt.close()
    await bot.send(event, ms.image(pic))
Exemple #3
0
async def stat_damage(bot:NoneBot, ctx:Context_T, args:ParseResult):
    bm = BattleMaster(ctx['group_id'])
    now = datetime.now()
    clan = _check_clan(bm)
    yyyy, mm, _ = bm.get_yyyymmdd(now)
    stat = bm.stat_damage(1, now)

    yn = len(stat)
    if not yn:
        await bot.send(ctx, f"{clan['name']}{yyyy}年{mm}月会战统计数据为空", at_sender=True)
        return

    stat.sort(key=lambda x: x[3][0], reverse=True)
    name = [ s[2] for s in stat ]
    y_pos = list(range(yn))
    y_size = 0.3 * yn + 1.0
    unit = 1e4
    unit_str = 'w'

    # convert to pre-sum
    for s in stat:
        d = s[3]
        d[0] = 0
        for i in range(2, 6):
            d[i] += d[i - 1]
    pre_sum_dmg = [
        [ s[3][b] for s in stat ] for b in range(6)
    ]

    # generate statistic figure
    fig, ax = plt.subplots()
    fig.set_size_inches(10, y_size)
    ax.set_title(f"{clan['name']}{yyyy}年{mm}月会战伤害统计")
    ax.set_yticks(y_pos)
    ax.set_yticklabels(name)
    ax.set_ylim((-0.6, yn - 0.4))
    ax.invert_yaxis()
    ax.set_xlabel('伤害')
    colors = ['#00a2e8', '#22b14c', '#b5e61d', '#fff200', '#ff7f27', '#ed1c24']
    bars = [ ax.barh(y_pos, pre_sum_dmg[b], align='center', color=colors[b]) for b in range(5, -1, -1) ]
    bars.reverse()
    ax.ticklabel_format(axis='x', style='plain')
    for b in range(1, 6):
        for i, rect in enumerate(bars[b]):
            x = (rect.get_width() + bars[b - 1][i].get_width()) / 2
            y = rect.get_y() + rect.get_height() / 2
            d = pre_sum_dmg[b][i] - pre_sum_dmg[b - 1][i]
            if d > unit:
                ax.text(x, y, f'{d/unit:.0f}{unit_str}', ha='center', va='center')
    plt.subplots_adjust(left=0.12, right=0.96, top=1 - 0.35 / y_size, bottom=0.55 / y_size)
    pic = util.fig2b64(plt)
    plt.close()
    
    msg = f"{ms.image(pic)}\n※分数统计请发送“!分数统计”"
    await bot.send(ctx, msg, at_sender=True)
Exemple #4
0
async def ss_rate(bot, ev):
    txt = ev.message.extract_plain_text().strip()
    if not txt:
        await bot.finish(ev,
                         '请在后面跟魂石数据\n示例:魂石评分 输出/坦克/奶妈天/地/荒攻击4伤害10暴击4气血3',
                         at_sender=True)

    pfbz = txt[:2]
    if pfbz not in ss_stds.keys():
        await bot.finish(
            ev,
            '魂石数据不正确,缺少评分模板(输出/坦克/奶妈)\n示例:魂石评分 输出/坦克/奶妈天/地/荒攻击4伤害10暴击4气血3',
            at_sender=True)
    ss_score = ss_stds[pfbz]
    txt = txt[2:]

    ss_type = txt[:1]
    if ss_type not in ss_limit.keys():
        await bot.finish(
            ev,
            '魂石数据不正确,缺少魂石类型(天地荒)\n示例:魂石评分 输出/坦克/奶妈天/地/荒攻击4伤害10暴击4气血3',
            at_sender=True)
    score = 0
    errmsg = ''
    txt = txt[1:]
    entry = []
    label = []
    labelmax = []
    pct = []
    yn = 0
    while len(txt) > 0:
        m = re.match(
            r'^(攻击|物攻|法攻|伤害|物伤|法伤|穿透|物穿|法穿|暴击|反伤|气血|物免|法免|物防|法防|暴抗)(10|[1-9])(\D|)',
            txt)
        if m is None:
            errmsg = "没有匹配到属性"
            break
        else:
            #判断属性是不是超了限制
            attr = m.group(1)
            if attr == "物攻" or attr == "法攻":
                attr = "攻击"
            elif attr == "物伤" or attr == "法伤":
                attr = "伤害"
            elif attr == "物穿" or attr == "法穿":
                attr = "穿透"

            if ss_limit[ss_type][attr] < int(
                    m.group(2)) or ss_min[ss_type][attr] > int(m.group(2)):
                errmsg = f"{attr}词条的值{m.group(2)}不在{ss_type}魂石允许值范围内{ss_min[ss_type][attr]}-{ss_limit[ss_type][attr]}"
                break
            entry.append(attr)
            label.append(m.group(2))
            labelmax.append(ss_limit[ss_type][attr])
            pct.append(round(int(m.group(2)) / ss_limit[ss_type][attr], 2))
            score += ss_score[attr] * int(m.group(2))
            yn += 1
        txt = txt[len(attr) + len(m.group(2)):]

    if errmsg == '':
        #生成图片
        map_vir = cm.get_cmap(name='autumn_r')
        norm = plt.Normalize(0, 1)
        norm_values = norm(pct)
        colors = map_vir(norm_values)
        redupct = [round(1 - p, 2) for p in pct]
        fig, ax = plt.subplots()
        y_pos = list(range(yn))
        fig.set_size_inches(5, 4)
        bars = ax.barh(y_pos,
                       pct,
                       height=0.5,
                       color=colors,
                       alpha=0.8,
                       align='center')
        bars2 = ax.barh(y_pos,
                        redupct,
                        height=0.5,
                        left=pct,
                        color="#e3e3e3",
                        alpha=0.8,
                        align='center')
        plt.text(x=0.5,
                 y=0.82,
                 s=f"{rankLv[ss_std(ss_type,score)]}",
                 fontproperties=my_font,
                 fontsize=40,
                 ha="center",
                 transform=fig.transFigure,
                 color=rankColor[ss_std(ss_type, score)])
        plt.text(x=0.78,
                 y=0.82,
                 s=f"{pfbz}:{score}分",
                 fontproperties=my_font,
                 fontsize=16,
                 ha="center",
                 color="#666666",
                 transform=fig.transFigure)

        ax.tick_params(axis='y', labelsize='x-large')
        [spine.set_visible(False) for spine in ax.spines.values()]
        ax.tick_params(bottom=False, left=False, labelbottom=False)
        ax.set_yticks(y_pos)
        ax.set_yticklabels(entry, fontproperties=my_font, fontsize="20")
        ax.set_xticks([])
        ax.invert_yaxis()
        i = 0
        for rect in bars:
            w = rect.get_width()
            ax.text(w - 0.01,
                    rect.get_y() + rect.get_height() / 2 + 0.03,
                    label[i],
                    color="white",
                    ha='right',
                    va='center',
                    fontproperties=my_font,
                    fontsize='x-large')
            i += 1
        i = 0
        for rect2 in bars2:
            ax.text(1.01,
                    rect2.get_y() + rect2.get_height() / 2 + 0.03,
                    labelmax[i],
                    ha='left',
                    va='center',
                    fontproperties=my_font,
                    fontsize='x-large')
            i += 1
        plt.subplots_adjust(left=0.15, right=0.9, top=0.82, bottom=0.1)
        ax.text(0,
                3.5,
                "评分方法可输入命令:评分标准 来查看",
                ha='left',
                va='center',
                fontsize='small',
                color="#444444")
        pic = util.fig2b64(plt)
        plt.close()
        await bot.finish(ev, f'\n{ms.image(pic)}', at_sender=True)
    else:
        await bot.finish(
            ev,
            f'魂石数据不正确:{errmsg}\n示例:魂石评分 输出/坦克/奶妈天/地/荒攻击4伤害10暴击4气血3\n属性词条缩写:攻击|物攻|法攻|伤害|物伤|法伤|穿透|物穿|法穿|暴击|反伤|气血|物免|法免|物防|法防|暴抗',
            at_sender=True)