cls.score

cls/score.py

  1"""
  2cls/score.py
  3"""
  4
  5from dataclasses import dataclass, field
  6from typing import Literal, Optional, cast
  7
  8from cls.types import ScoreDataDict
  9from libs.functions.score import calculation_point
 10
 11
 12@dataclass
 13class Score:
 14    """プレイヤー成績"""
 15    name: str = field(default="")
 16    """プレイヤー名"""
 17    r_str: str = field(default="")
 18    """入力された素点情報(文字列)"""
 19    rpoint: int = field(default=0)
 20    """素点(入力文字列評価後)"""
 21    point: float = field(default=0.0)
 22    """獲得ポイント"""
 23    rank: int = field(default=0)
 24    """獲得順位"""
 25
 26    def has_valid_data(self) -> bool:
 27        """有効なデータを持っているかチェック"""
 28        return self != Score()
 29
 30    def to_dict(self, prefix: str | None = None) -> dict:
 31        """データを辞書で返す
 32
 33        Args:
 34            prefix (str | None, optional): キーに付与する接頭辞. Defaults to None.
 35
 36        Returns:
 37            dict: 返却する辞書
 38        """
 39
 40        ret_dict: dict = {}
 41        prefix = "" if prefix is None else f"{prefix}_"
 42        for k, v in self.__dict__.items():
 43            if k == "r_str":
 44                k = "str"
 45            ret_dict[f"{prefix}{k}"] = v
 46
 47        return ret_dict
 48
 49
 50@dataclass
 51class GameResult:
 52    """ゲーム結果"""
 53    ts: str = field(default="")
 54    """タイムスタンプ"""
 55    p1: Score = field(default_factory=Score)
 56    """東家成績"""
 57    p2: Score = field(default_factory=Score)
 58    """南家成績"""
 59    p3: Score = field(default_factory=Score)
 60    """西家成績"""
 61    p4: Score = field(default_factory=Score)
 62    """北家成績"""
 63    comment: Optional[str] = field(default=None)
 64    """ゲームコメント"""
 65    deposit: int = field(default=0)
 66    """供託"""
 67    rule_version: str = field(default="")
 68    """ルールバージョン"""
 69
 70    def __bool__(self) -> bool:
 71        return all(self.to_list("name") + self.to_list("str"))
 72
 73    def has_valid_data(self) -> bool:
 74        """有効なデータを持っているかチェック"""
 75        return all([
 76            self.ts != GameResult.ts,
 77            self.p1.has_valid_data(),
 78            self.p2.has_valid_data(),
 79            self.p3.has_valid_data(),
 80            self.p4.has_valid_data(),
 81            all(self.to_list("rank")),
 82        ])
 83
 84    def set(self, **kwargs) -> None:
 85        """テータ取り込み"""
 86        for prefix in ("p1", "p2", "p3", "p4"):
 87            x = {str(k).replace(f"{prefix}_", ""): v for k, v in kwargs.items() if str(k).startswith(f"{prefix}_")}
 88            prefix_obj = getattr(self, prefix)
 89            for k, v in x.items():
 90                match k:
 91                    case "name":
 92                        setattr(prefix_obj, "name", str(v))
 93                    case "str" | "r_str":
 94                        setattr(prefix_obj, "r_str", str(v))
 95                    case "rpoint":
 96                        if isinstance(v, int):
 97                            setattr(prefix_obj, "rpoint", int(v))
 98                    case "point":
 99                        if isinstance(v, (float, int)):
100                            setattr(prefix_obj, "point", float(v))
101                    case "rank":
102                        if isinstance(v, int):
103                            setattr(prefix_obj, "rank", int(v))
104
105        if "ts" in kwargs:
106            self.ts = kwargs["ts"]
107        if "rule_version" in kwargs:
108            self.rule_version = str(kwargs["rule_version"])
109        if "deposit" in kwargs:
110            self.deposit = int(kwargs["deposit"])
111        if "comment" in kwargs:
112            self.comment = kwargs["comment"]
113
114    def to_dict(self) -> ScoreDataDict:
115        """データを辞書で返す
116
117        Returns:
118            ScoreDataDict: スコアデータ
119        """
120
121        ret_dict: ScoreDataDict = {}
122        ret_dict.update({
123            "ts": self.ts,
124            "comment": self.comment,
125            "rule_version": self.rule_version,
126            "deposit": self.deposit,
127            **self.p1.to_dict("p1"),
128            **self.p2.to_dict("p2"),
129            **self.p3.to_dict("p3"),
130            **self.p4.to_dict("p4"),
131        })
132
133        return ret_dict
134
135    def to_text(self, kind: Literal["simple", "detail"] = "simple") -> str:
136        """データをテキストで返す
137
138        Args:
139            kind (Literal, optional): 表示形式
140                - *simple* 簡易情報 (Default)
141                - *detail* 詳細情報
142
143        Returns:
144            str: スコアデータ
145        """
146
147        ret_text: str = ""
148        match kind:
149            case "simple":
150                ret_text += f"[{self.p1.name} {self.p1.r_str}]"
151                ret_text += f"[{self.p2.name} {self.p2.r_str}]"
152                ret_text += f"[{self.p3.name} {self.p3.r_str}]"
153                ret_text += f"[{self.p4.name} {self.p4.r_str}]"
154                ret_text += f"[{self.comment if self.comment else ""}]"
155            case "detail":
156                ret_text += f"[{self.p1.rank}{self.p1.name} {self.p1.rpoint * 100}点 ({self.p1.point}pt)] ".replace("-", "▲")
157                ret_text += f"[{self.p2.rank}{self.p2.name} {self.p2.rpoint * 100}点 ({self.p2.point}pt)] ".replace("-", "▲")
158                ret_text += f"[{self.p3.rank}{self.p3.name} {self.p3.rpoint * 100}点 ({self.p3.point}pt)] ".replace("-", "▲")
159                ret_text += f"[{self.p4.rank}{self.p4.name} {self.p4.rpoint * 100}点 ({self.p4.point}pt)] ".replace("-", "▲")
160                ret_text += f"[{self.comment if self.comment else ""}]"
161
162        return ret_text
163
164    def to_list(self, kind: Literal["name", "str", "rpoint", "point", "rank"] = "name") -> list[str | int | float]:
165        """指定データをリストで返す
166
167        Args:
168            kind (Literal, optional): 取得内容
169                - *name*: プレイヤー名 (Default)
170                - *str*: 入力された素点情報
171                - *rpoint*: 素点
172                - *point*: ポイント
173                - *rank*: 順位
174
175        Returns:
176            list[str | int | float]: リスト
177        """
178
179        ret_list: list = []
180        match kind:
181            case "name":
182                ret_list = [self.p1.name, self.p2.name, self.p3.name, self.p4.name]
183            case "str":
184                ret_list = [self.p1.r_str, self.p2.r_str, self.p3.r_str, self.p4.r_str]
185            case "rpoint":
186                ret_list = [self.p1.rpoint, self.p2.rpoint, self.p3.rpoint, self.p4.rpoint]
187            case "point":
188                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
189            case "point":
190                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
191            case "rank":
192                ret_list = [self.p1.rank, self.p2.rank, self.p3.rank, self.p4.rank]
193
194        return ret_list
195
196    def rpoint_sum(self) -> int:
197        """素点合計
198
199        Returns:
200            int: 素点合計
201        """
202
203        if not all(self.to_list("rank")):  # 順位が確定していない場合は先に計算
204            self.calc()
205
206        return sum(cast(list[int], self.to_list("rpoint")))
207
208    def calc(self, **kwargs):
209        """獲得ポイント計算"""
210        if kwargs:
211            self.set(**kwargs)
212
213        if all([self.p1.has_valid_data(), self.p2.has_valid_data(), self.p3.has_valid_data(), self.p4.has_valid_data()]):
214            self.set(**calculation_point(cast(list[str], self.to_list("str"))))
@dataclass
class Score:
13@dataclass
14class Score:
15    """プレイヤー成績"""
16    name: str = field(default="")
17    """プレイヤー名"""
18    r_str: str = field(default="")
19    """入力された素点情報(文字列)"""
20    rpoint: int = field(default=0)
21    """素点(入力文字列評価後)"""
22    point: float = field(default=0.0)
23    """獲得ポイント"""
24    rank: int = field(default=0)
25    """獲得順位"""
26
27    def has_valid_data(self) -> bool:
28        """有効なデータを持っているかチェック"""
29        return self != Score()
30
31    def to_dict(self, prefix: str | None = None) -> dict:
32        """データを辞書で返す
33
34        Args:
35            prefix (str | None, optional): キーに付与する接頭辞. Defaults to None.
36
37        Returns:
38            dict: 返却する辞書
39        """
40
41        ret_dict: dict = {}
42        prefix = "" if prefix is None else f"{prefix}_"
43        for k, v in self.__dict__.items():
44            if k == "r_str":
45                k = "str"
46            ret_dict[f"{prefix}{k}"] = v
47
48        return ret_dict

プレイヤー成績

Score( name: str = '', r_str: str = '', rpoint: int = 0, point: float = 0.0, rank: int = 0)
name: str = ''

プレイヤー名

r_str: str = ''

入力された素点情報(文字列)

rpoint: int = 0

素点(入力文字列評価後)

point: float = 0.0

獲得ポイント

rank: int = 0

獲得順位

def has_valid_data(self) -> bool:
27    def has_valid_data(self) -> bool:
28        """有効なデータを持っているかチェック"""
29        return self != Score()

有効なデータを持っているかチェック

def to_dict(self, prefix: str | None = None) -> dict:
31    def to_dict(self, prefix: str | None = None) -> dict:
32        """データを辞書で返す
33
34        Args:
35            prefix (str | None, optional): キーに付与する接頭辞. Defaults to None.
36
37        Returns:
38            dict: 返却する辞書
39        """
40
41        ret_dict: dict = {}
42        prefix = "" if prefix is None else f"{prefix}_"
43        for k, v in self.__dict__.items():
44            if k == "r_str":
45                k = "str"
46            ret_dict[f"{prefix}{k}"] = v
47
48        return ret_dict

データを辞書で返す

Arguments:
  • prefix (str | None, optional): キーに付与する接頭辞. Defaults to None.
Returns:

dict: 返却する辞書

@dataclass
class GameResult:
 51@dataclass
 52class GameResult:
 53    """ゲーム結果"""
 54    ts: str = field(default="")
 55    """タイムスタンプ"""
 56    p1: Score = field(default_factory=Score)
 57    """東家成績"""
 58    p2: Score = field(default_factory=Score)
 59    """南家成績"""
 60    p3: Score = field(default_factory=Score)
 61    """西家成績"""
 62    p4: Score = field(default_factory=Score)
 63    """北家成績"""
 64    comment: Optional[str] = field(default=None)
 65    """ゲームコメント"""
 66    deposit: int = field(default=0)
 67    """供託"""
 68    rule_version: str = field(default="")
 69    """ルールバージョン"""
 70
 71    def __bool__(self) -> bool:
 72        return all(self.to_list("name") + self.to_list("str"))
 73
 74    def has_valid_data(self) -> bool:
 75        """有効なデータを持っているかチェック"""
 76        return all([
 77            self.ts != GameResult.ts,
 78            self.p1.has_valid_data(),
 79            self.p2.has_valid_data(),
 80            self.p3.has_valid_data(),
 81            self.p4.has_valid_data(),
 82            all(self.to_list("rank")),
 83        ])
 84
 85    def set(self, **kwargs) -> None:
 86        """テータ取り込み"""
 87        for prefix in ("p1", "p2", "p3", "p4"):
 88            x = {str(k).replace(f"{prefix}_", ""): v for k, v in kwargs.items() if str(k).startswith(f"{prefix}_")}
 89            prefix_obj = getattr(self, prefix)
 90            for k, v in x.items():
 91                match k:
 92                    case "name":
 93                        setattr(prefix_obj, "name", str(v))
 94                    case "str" | "r_str":
 95                        setattr(prefix_obj, "r_str", str(v))
 96                    case "rpoint":
 97                        if isinstance(v, int):
 98                            setattr(prefix_obj, "rpoint", int(v))
 99                    case "point":
100                        if isinstance(v, (float, int)):
101                            setattr(prefix_obj, "point", float(v))
102                    case "rank":
103                        if isinstance(v, int):
104                            setattr(prefix_obj, "rank", int(v))
105
106        if "ts" in kwargs:
107            self.ts = kwargs["ts"]
108        if "rule_version" in kwargs:
109            self.rule_version = str(kwargs["rule_version"])
110        if "deposit" in kwargs:
111            self.deposit = int(kwargs["deposit"])
112        if "comment" in kwargs:
113            self.comment = kwargs["comment"]
114
115    def to_dict(self) -> ScoreDataDict:
116        """データを辞書で返す
117
118        Returns:
119            ScoreDataDict: スコアデータ
120        """
121
122        ret_dict: ScoreDataDict = {}
123        ret_dict.update({
124            "ts": self.ts,
125            "comment": self.comment,
126            "rule_version": self.rule_version,
127            "deposit": self.deposit,
128            **self.p1.to_dict("p1"),
129            **self.p2.to_dict("p2"),
130            **self.p3.to_dict("p3"),
131            **self.p4.to_dict("p4"),
132        })
133
134        return ret_dict
135
136    def to_text(self, kind: Literal["simple", "detail"] = "simple") -> str:
137        """データをテキストで返す
138
139        Args:
140            kind (Literal, optional): 表示形式
141                - *simple* 簡易情報 (Default)
142                - *detail* 詳細情報
143
144        Returns:
145            str: スコアデータ
146        """
147
148        ret_text: str = ""
149        match kind:
150            case "simple":
151                ret_text += f"[{self.p1.name} {self.p1.r_str}]"
152                ret_text += f"[{self.p2.name} {self.p2.r_str}]"
153                ret_text += f"[{self.p3.name} {self.p3.r_str}]"
154                ret_text += f"[{self.p4.name} {self.p4.r_str}]"
155                ret_text += f"[{self.comment if self.comment else ""}]"
156            case "detail":
157                ret_text += f"[{self.p1.rank}{self.p1.name} {self.p1.rpoint * 100}点 ({self.p1.point}pt)] ".replace("-", "▲")
158                ret_text += f"[{self.p2.rank}{self.p2.name} {self.p2.rpoint * 100}点 ({self.p2.point}pt)] ".replace("-", "▲")
159                ret_text += f"[{self.p3.rank}{self.p3.name} {self.p3.rpoint * 100}点 ({self.p3.point}pt)] ".replace("-", "▲")
160                ret_text += f"[{self.p4.rank}{self.p4.name} {self.p4.rpoint * 100}点 ({self.p4.point}pt)] ".replace("-", "▲")
161                ret_text += f"[{self.comment if self.comment else ""}]"
162
163        return ret_text
164
165    def to_list(self, kind: Literal["name", "str", "rpoint", "point", "rank"] = "name") -> list[str | int | float]:
166        """指定データをリストで返す
167
168        Args:
169            kind (Literal, optional): 取得内容
170                - *name*: プレイヤー名 (Default)
171                - *str*: 入力された素点情報
172                - *rpoint*: 素点
173                - *point*: ポイント
174                - *rank*: 順位
175
176        Returns:
177            list[str | int | float]: リスト
178        """
179
180        ret_list: list = []
181        match kind:
182            case "name":
183                ret_list = [self.p1.name, self.p2.name, self.p3.name, self.p4.name]
184            case "str":
185                ret_list = [self.p1.r_str, self.p2.r_str, self.p3.r_str, self.p4.r_str]
186            case "rpoint":
187                ret_list = [self.p1.rpoint, self.p2.rpoint, self.p3.rpoint, self.p4.rpoint]
188            case "point":
189                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
190            case "point":
191                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
192            case "rank":
193                ret_list = [self.p1.rank, self.p2.rank, self.p3.rank, self.p4.rank]
194
195        return ret_list
196
197    def rpoint_sum(self) -> int:
198        """素点合計
199
200        Returns:
201            int: 素点合計
202        """
203
204        if not all(self.to_list("rank")):  # 順位が確定していない場合は先に計算
205            self.calc()
206
207        return sum(cast(list[int], self.to_list("rpoint")))
208
209    def calc(self, **kwargs):
210        """獲得ポイント計算"""
211        if kwargs:
212            self.set(**kwargs)
213
214        if all([self.p1.has_valid_data(), self.p2.has_valid_data(), self.p3.has_valid_data(), self.p4.has_valid_data()]):
215            self.set(**calculation_point(cast(list[str], self.to_list("str"))))

ゲーム結果

GameResult( ts: str = '', p1: Score = <factory>, p2: Score = <factory>, p3: Score = <factory>, p4: Score = <factory>, comment: Optional[str] = None, deposit: int = 0, rule_version: str = '')
ts: str = ''

タイムスタンプ

p1: Score

東家成績

p2: Score

南家成績

p3: Score

西家成績

p4: Score

北家成績

comment: Optional[str] = None

ゲームコメント

deposit: int = 0

供託

rule_version: str = ''

ルールバージョン

def has_valid_data(self) -> bool:
74    def has_valid_data(self) -> bool:
75        """有効なデータを持っているかチェック"""
76        return all([
77            self.ts != GameResult.ts,
78            self.p1.has_valid_data(),
79            self.p2.has_valid_data(),
80            self.p3.has_valid_data(),
81            self.p4.has_valid_data(),
82            all(self.to_list("rank")),
83        ])

有効なデータを持っているかチェック

def set(self, **kwargs) -> None:
 85    def set(self, **kwargs) -> None:
 86        """テータ取り込み"""
 87        for prefix in ("p1", "p2", "p3", "p4"):
 88            x = {str(k).replace(f"{prefix}_", ""): v for k, v in kwargs.items() if str(k).startswith(f"{prefix}_")}
 89            prefix_obj = getattr(self, prefix)
 90            for k, v in x.items():
 91                match k:
 92                    case "name":
 93                        setattr(prefix_obj, "name", str(v))
 94                    case "str" | "r_str":
 95                        setattr(prefix_obj, "r_str", str(v))
 96                    case "rpoint":
 97                        if isinstance(v, int):
 98                            setattr(prefix_obj, "rpoint", int(v))
 99                    case "point":
100                        if isinstance(v, (float, int)):
101                            setattr(prefix_obj, "point", float(v))
102                    case "rank":
103                        if isinstance(v, int):
104                            setattr(prefix_obj, "rank", int(v))
105
106        if "ts" in kwargs:
107            self.ts = kwargs["ts"]
108        if "rule_version" in kwargs:
109            self.rule_version = str(kwargs["rule_version"])
110        if "deposit" in kwargs:
111            self.deposit = int(kwargs["deposit"])
112        if "comment" in kwargs:
113            self.comment = kwargs["comment"]

テータ取り込み

def to_dict(self) -> cls.types.ScoreDataDict:
115    def to_dict(self) -> ScoreDataDict:
116        """データを辞書で返す
117
118        Returns:
119            ScoreDataDict: スコアデータ
120        """
121
122        ret_dict: ScoreDataDict = {}
123        ret_dict.update({
124            "ts": self.ts,
125            "comment": self.comment,
126            "rule_version": self.rule_version,
127            "deposit": self.deposit,
128            **self.p1.to_dict("p1"),
129            **self.p2.to_dict("p2"),
130            **self.p3.to_dict("p3"),
131            **self.p4.to_dict("p4"),
132        })
133
134        return ret_dict

データを辞書で返す

Returns:

ScoreDataDict: スコアデータ

def to_text(self, kind: Literal['simple', 'detail'] = 'simple') -> str:
136    def to_text(self, kind: Literal["simple", "detail"] = "simple") -> str:
137        """データをテキストで返す
138
139        Args:
140            kind (Literal, optional): 表示形式
141                - *simple* 簡易情報 (Default)
142                - *detail* 詳細情報
143
144        Returns:
145            str: スコアデータ
146        """
147
148        ret_text: str = ""
149        match kind:
150            case "simple":
151                ret_text += f"[{self.p1.name} {self.p1.r_str}]"
152                ret_text += f"[{self.p2.name} {self.p2.r_str}]"
153                ret_text += f"[{self.p3.name} {self.p3.r_str}]"
154                ret_text += f"[{self.p4.name} {self.p4.r_str}]"
155                ret_text += f"[{self.comment if self.comment else ""}]"
156            case "detail":
157                ret_text += f"[{self.p1.rank}{self.p1.name} {self.p1.rpoint * 100}点 ({self.p1.point}pt)] ".replace("-", "▲")
158                ret_text += f"[{self.p2.rank}{self.p2.name} {self.p2.rpoint * 100}点 ({self.p2.point}pt)] ".replace("-", "▲")
159                ret_text += f"[{self.p3.rank}{self.p3.name} {self.p3.rpoint * 100}点 ({self.p3.point}pt)] ".replace("-", "▲")
160                ret_text += f"[{self.p4.rank}{self.p4.name} {self.p4.rpoint * 100}点 ({self.p4.point}pt)] ".replace("-", "▲")
161                ret_text += f"[{self.comment if self.comment else ""}]"
162
163        return ret_text

データをテキストで返す

Arguments:
  • kind (Literal, optional): 表示形式
    • simple 簡易情報 (Default)
    • detail 詳細情報
Returns:

str: スコアデータ

def to_list( self, kind: Literal['name', 'str', 'rpoint', 'point', 'rank'] = 'name') -> list[str | int | float]:
165    def to_list(self, kind: Literal["name", "str", "rpoint", "point", "rank"] = "name") -> list[str | int | float]:
166        """指定データをリストで返す
167
168        Args:
169            kind (Literal, optional): 取得内容
170                - *name*: プレイヤー名 (Default)
171                - *str*: 入力された素点情報
172                - *rpoint*: 素点
173                - *point*: ポイント
174                - *rank*: 順位
175
176        Returns:
177            list[str | int | float]: リスト
178        """
179
180        ret_list: list = []
181        match kind:
182            case "name":
183                ret_list = [self.p1.name, self.p2.name, self.p3.name, self.p4.name]
184            case "str":
185                ret_list = [self.p1.r_str, self.p2.r_str, self.p3.r_str, self.p4.r_str]
186            case "rpoint":
187                ret_list = [self.p1.rpoint, self.p2.rpoint, self.p3.rpoint, self.p4.rpoint]
188            case "point":
189                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
190            case "point":
191                ret_list = [self.p1.point, self.p2.point, self.p3.point, self.p4.point]
192            case "rank":
193                ret_list = [self.p1.rank, self.p2.rank, self.p3.rank, self.p4.rank]
194
195        return ret_list

指定データをリストで返す

Arguments:
  • kind (Literal, optional): 取得内容
    • name: プレイヤー名 (Default)
    • str: 入力された素点情報
    • rpoint: 素点
    • point: ポイント
    • rank: 順位
Returns:

list[str | int | float]: リスト

def rpoint_sum(self) -> int:
197    def rpoint_sum(self) -> int:
198        """素点合計
199
200        Returns:
201            int: 素点合計
202        """
203
204        if not all(self.to_list("rank")):  # 順位が確定していない場合は先に計算
205            self.calc()
206
207        return sum(cast(list[int], self.to_list("rpoint")))

素点合計

Returns:

int: 素点合計

def calc(self, **kwargs):
209    def calc(self, **kwargs):
210        """獲得ポイント計算"""
211        if kwargs:
212            self.set(**kwargs)
213
214        if all([self.p1.has_valid_data(), self.p2.has_valid_data(), self.p3.has_valid_data(), self.p4.has_valid_data()]):
215            self.set(**calculation_point(cast(list[str], self.to_list("str"))))

獲得ポイント計算