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
プレイヤー成績
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 = '')
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"]
テータ取り込み
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"))))
獲得ポイント計算