libs.commands.ranking.rating

libs/commands/results/rating.py

  1"""
  2libs/commands/results/rating.py
  3"""
  4
  5import pandas as pd
  6
  7import libs.global_value as g
  8from cls.types import GameInfoDict
  9from libs.data import aggregate, loader
 10from libs.functions import message
 11from libs.utils import formatter
 12
 13
 14def aggregation() -> tuple[str, dict, dict]:
 15    """レーティングを集計して返す
 16
 17    Returns:
 18        tuple[str, dict, dict]:
 19        - str: ヘッダ情報
 20        - dict: 集計データ
 21        - dict: 生成ファイルの情報
 22    """
 23
 24    # 情報ヘッダ
 25    add_text: str = ""
 26    headline: str = "*【レーティング】*\n"
 27
 28    # データ収集
 29    # g.params.update(guest_skip=False)  # 2ゲスト戦強制取り込み
 30    game_info: GameInfoDict = aggregate.game_info()
 31    if not game_info["game_count"]:  # 検索結果が0件のとき
 32        headline += "\t" + message.reply(message="no_hits")
 33        return (headline, {}, {})
 34
 35    df_results = loader.read_data("ranking/results.sql").set_index("name")
 36    df_ratings = aggregate.calculation_rating()
 37
 38    # 最終的なレーティング
 39    final = df_ratings.ffill().tail(1).transpose()
 40    final.columns = ["rate"]
 41    final["name"] = final.copy().index
 42
 43    df = pd.merge(df_results, final, on=["name"]).sort_values(by="rate", ascending=False)
 44    df = df.query("count >= @g.params['stipulated']").copy()  # 足切り
 45
 46    # 集計対象外データの削除
 47    if g.params.get("unregistered_replace"):  # 個人戦
 48        for player in df.itertuples():
 49            if player.name not in g.member_list:
 50                df = df.copy().drop(player.Index)
 51
 52    if not g.params.get("individual"):  # チーム戦
 53        df = df.copy().query("name != '未所属'")
 54
 55    # 順位偏差 / 得点偏差
 56    df["point_dev"] = (df["rpoint_avg"] - df["rpoint_avg"].mean()) / df["rpoint_avg"].std(ddof=0) * 10 + 50
 57    df["rank_dev"] = (df["rank_avg"] - df["rank_avg"].mean()) / df["rank_avg"].std(ddof=0) * -10 + 50
 58
 59    # 段位
 60    if g.cfg.badge.grade.display:
 61        for idx in df.index:
 62            name = str(df.at[idx, "name"]).replace(f"({g.cfg.setting.guest_mark})", "")
 63            df.at[idx, "grade"] = message.badge_grade(name, False)
 64
 65    # 表示
 66    if g.params.get("anonymous"):
 67        mapping_dict = formatter.anonymous_mapping(df["name"].unique().tolist())
 68        df["name"] = df["name"].replace(mapping_dict)
 69
 70    if df.empty:
 71        headline += "\t" + message.reply(message="no_target")
 72        return (headline, {}, {})
 73
 74    headline += message.header(game_info, add_text, 1)
 75    df = formatter.df_rename(df.filter(
 76        items=[
 77            "name", "rate", "rank_distr", "rank_avg", "rank_dev", "rpoint_avg", "point_dev", "grade"
 78        ]
 79    ), short=False).copy()
 80    df = df.drop(columns=[x for x in g.cfg.dropitems.ranking if x in df.columns.to_list()])  # 非表示項目
 81
 82    msg: dict = {}
 83    table_param: dict = {
 84        "index": False,
 85        "tablefmt": "simple",
 86        "numalign": "right",
 87        "floatfmt": ["", ".1f", "", ".2f", ".0f", ".1f", ".0f"],
 88    }
 89
 90    step = 30
 91    length = len(df)
 92    for i in range(int(length / step) + 1):
 93        s = step * i
 94        e = step * (i + 1)
 95        if e + step / 2 > length:
 96            table = df[s:].to_markdown(**table_param)
 97            msg[s] = f"```\n{table}\n```\n"
 98            break
 99
100        table = df[s:e].to_markdown(**table_param)
101        msg[s] = f"```\n{table}\n```\n"
102
103    prefix_rating: str = "rating"
104    if g.params.get("filename"):
105        prefix_rating = f"{g.params["filename"]}"
106
107    file_list: dict = {"レーティング": ""}
108    match g.params.get("format", "default").lower().lower():
109        case "csv":
110            file_list = {
111                "レーティング": formatter.save_output(df, "csv", f"{prefix_rating}.csv", headline),
112            }
113        case "text" | "txt":
114            file_list = {
115                "レーティング": formatter.save_output(df, "txt", f"{prefix_rating}.txt", headline),
116            }
117
118    return (headline, msg, file_list)
def aggregation() -> tuple[str, dict, dict]:
 15def aggregation() -> tuple[str, dict, dict]:
 16    """レーティングを集計して返す
 17
 18    Returns:
 19        tuple[str, dict, dict]:
 20        - str: ヘッダ情報
 21        - dict: 集計データ
 22        - dict: 生成ファイルの情報
 23    """
 24
 25    # 情報ヘッダ
 26    add_text: str = ""
 27    headline: str = "*【レーティング】*\n"
 28
 29    # データ収集
 30    # g.params.update(guest_skip=False)  # 2ゲスト戦強制取り込み
 31    game_info: GameInfoDict = aggregate.game_info()
 32    if not game_info["game_count"]:  # 検索結果が0件のとき
 33        headline += "\t" + message.reply(message="no_hits")
 34        return (headline, {}, {})
 35
 36    df_results = loader.read_data("ranking/results.sql").set_index("name")
 37    df_ratings = aggregate.calculation_rating()
 38
 39    # 最終的なレーティング
 40    final = df_ratings.ffill().tail(1).transpose()
 41    final.columns = ["rate"]
 42    final["name"] = final.copy().index
 43
 44    df = pd.merge(df_results, final, on=["name"]).sort_values(by="rate", ascending=False)
 45    df = df.query("count >= @g.params['stipulated']").copy()  # 足切り
 46
 47    # 集計対象外データの削除
 48    if g.params.get("unregistered_replace"):  # 個人戦
 49        for player in df.itertuples():
 50            if player.name not in g.member_list:
 51                df = df.copy().drop(player.Index)
 52
 53    if not g.params.get("individual"):  # チーム戦
 54        df = df.copy().query("name != '未所属'")
 55
 56    # 順位偏差 / 得点偏差
 57    df["point_dev"] = (df["rpoint_avg"] - df["rpoint_avg"].mean()) / df["rpoint_avg"].std(ddof=0) * 10 + 50
 58    df["rank_dev"] = (df["rank_avg"] - df["rank_avg"].mean()) / df["rank_avg"].std(ddof=0) * -10 + 50
 59
 60    # 段位
 61    if g.cfg.badge.grade.display:
 62        for idx in df.index:
 63            name = str(df.at[idx, "name"]).replace(f"({g.cfg.setting.guest_mark})", "")
 64            df.at[idx, "grade"] = message.badge_grade(name, False)
 65
 66    # 表示
 67    if g.params.get("anonymous"):
 68        mapping_dict = formatter.anonymous_mapping(df["name"].unique().tolist())
 69        df["name"] = df["name"].replace(mapping_dict)
 70
 71    if df.empty:
 72        headline += "\t" + message.reply(message="no_target")
 73        return (headline, {}, {})
 74
 75    headline += message.header(game_info, add_text, 1)
 76    df = formatter.df_rename(df.filter(
 77        items=[
 78            "name", "rate", "rank_distr", "rank_avg", "rank_dev", "rpoint_avg", "point_dev", "grade"
 79        ]
 80    ), short=False).copy()
 81    df = df.drop(columns=[x for x in g.cfg.dropitems.ranking if x in df.columns.to_list()])  # 非表示項目
 82
 83    msg: dict = {}
 84    table_param: dict = {
 85        "index": False,
 86        "tablefmt": "simple",
 87        "numalign": "right",
 88        "floatfmt": ["", ".1f", "", ".2f", ".0f", ".1f", ".0f"],
 89    }
 90
 91    step = 30
 92    length = len(df)
 93    for i in range(int(length / step) + 1):
 94        s = step * i
 95        e = step * (i + 1)
 96        if e + step / 2 > length:
 97            table = df[s:].to_markdown(**table_param)
 98            msg[s] = f"```\n{table}\n```\n"
 99            break
100
101        table = df[s:e].to_markdown(**table_param)
102        msg[s] = f"```\n{table}\n```\n"
103
104    prefix_rating: str = "rating"
105    if g.params.get("filename"):
106        prefix_rating = f"{g.params["filename"]}"
107
108    file_list: dict = {"レーティング": ""}
109    match g.params.get("format", "default").lower().lower():
110        case "csv":
111            file_list = {
112                "レーティング": formatter.save_output(df, "csv", f"{prefix_rating}.csv", headline),
113            }
114        case "text" | "txt":
115            file_list = {
116                "レーティング": formatter.save_output(df, "txt", f"{prefix_rating}.txt", headline),
117            }
118
119    return (headline, msg, file_list)

レーティングを集計して返す

Returns:

tuple[str, dict, dict]:

  • str: ヘッダ情報
  • dict: 集計データ
  • dict: 生成ファイルの情報