21
21
from textual .screen import Screen
22
22
from textual .widgets import (Button , Checkbox , Footer , Header , Input , Label ,
23
23
LoadingIndicator , Log , Markdown , Pretty , Rule ,
24
- Static )
24
+ Digits , Static )
25
25
26
26
from action import Action
27
27
from liqi import LiqiProto , MsgType
28
28
from majsoul2mjai import MajsoulBridge
29
29
from libriichi_helper import meta_to_recommend , state_to_tehai
30
- from tileUnicode import TILE_2_UNICODE_ART_RICH , TILE_2_UNICODE , VERTICLE_RULE , HAI_VALUE , EMPTY_VERTICAL_RULE
31
-
30
+ from tileUnicode import ( TILE_2_UNICODE_ART_RICH , TILE_2_UNICODE , HAI_VALUE ,
31
+ VERTICAL_RULE , EMPTY_VERTICAL_RULE , TILE_LIST )
32
32
33
33
submission = 'players/bot.zip'
34
34
PORT_NUM = 28680
41
41
ENABLE_PLAYWRIGHT = settings ["Playwright" ]["enable" ]
42
42
43
43
44
+ class Recommandation (Horizontal ):
45
+ def __init__ (self , recommand_idx : int , * args , ** kwargs ) -> None :
46
+ super ().__init__ (* args , ** kwargs )
47
+ self .recommand_idx = recommand_idx
48
+
49
+ def compose (self ) -> ComposeResult :
50
+ self .action = Button ("Akagi" , classes = "action_none recommand_button" , variant = "default" ) # 10
51
+ self .pai = Label (TILE_2_UNICODE_ART_RICH ["?" ]) # 8
52
+ self .vertical_rule = Label (EMPTY_VERTICAL_RULE ) # 1
53
+ self .consumes = [Label (TILE_2_UNICODE_ART_RICH ["?" ]) for _ in range (3 )] # 8*3
54
+ self .action_container = Horizontal (self .action , self .pai , self .vertical_rule , * self .consumes , classes = "action_container" )
55
+ self .weight = Digits ("0.0" , classes = "recommand_digit" )
56
+
57
+ yield self .action_container
58
+ yield self .weight
59
+
60
+ def update (self , mjai_msg , state ):
61
+ if len (mjai_msg ['meta' ]) <= self .recommand_idx :
62
+ self .action .label = "Akagi"
63
+ self .action .add_class ("action_none" )
64
+ self .pai .update (TILE_2_UNICODE_ART_RICH ["?" ])
65
+ self .vertical_rule .update (EMPTY_VERTICAL_RULE )
66
+ for i in range (3 ):
67
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH ["?" ])
68
+ self .weight .update ("0.0" )
69
+ return
70
+ recommand = mjai_msg ['meta' ][self .recommand_idx ]
71
+ for action_class in self .action .classes :
72
+ if "action_" in action_class :
73
+ self .action .remove_class (action_class )
74
+ self .weight .update (f"{ (recommand [1 ]* 100 ):.2f} " )
75
+ if recommand [0 ] in TILE_LIST :
76
+ self .action .label = recommand [0 ]
77
+ self .action .add_class ("action_" + recommand [0 ])
78
+ self .pai .update (TILE_2_UNICODE_ART_RICH [recommand [0 ]])
79
+ self .vertical_rule .update (EMPTY_VERTICAL_RULE )
80
+ for i in range (3 ):
81
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH ["?" ])
82
+ elif recommand [0 ] in ['chi_low' , 'chi_mid' , 'chi_high' ]:
83
+ self .action .label = "chi"
84
+ self .action .add_class ("action_chi" )
85
+ last_kawa_tile = state .last_kawa_tile ()
86
+ self .pai .update (TILE_2_UNICODE_ART_RICH [last_kawa_tile ])
87
+ self .vertical_rule .update (VERTICAL_RULE )
88
+ last_kawa_tile_idx = TILE_LIST .index (last_kawa_tile )
89
+ match recommand [0 ]:
90
+ case 'chi_low' :
91
+ self .consumes [0 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx - 2 ]])
92
+ self .consumes [1 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx - 1 ]])
93
+ case 'chi_mid' :
94
+ self .consumes [0 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx - 1 ]])
95
+ self .consumes [1 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx + 1 ]])
96
+ case 'chi_high' :
97
+ self .consumes [0 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx + 1 ]])
98
+ self .consumes [1 ].update (TILE_2_UNICODE_ART_RICH [TILE_LIST [last_kawa_tile_idx + 2 ]])
99
+ self .consumes [2 ].update (TILE_2_UNICODE_ART_RICH ["?" ])
100
+ elif recommand [0 ] in ['pon' ]:
101
+ self .action .label = "pon"
102
+ self .action .add_class ("action_pon" )
103
+ last_kawa_tile = state .last_kawa_tile ()
104
+ self .pai .update (TILE_2_UNICODE_ART_RICH [last_kawa_tile ])
105
+ self .vertical_rule .update (VERTICAL_RULE )
106
+ for i in range (2 ):
107
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH [last_kawa_tile ])
108
+ self .consumes [2 ].update (TILE_2_UNICODE_ART_RICH ["?" ])
109
+ elif recommand [0 ] in ['kan_select' ]:
110
+ # The recommandation only shows kan_select, but not ['daiminkan', 'ankan', 'kakan'],
111
+ # this is due to the Mortal model structure limitations.
112
+ # We can only know the model wants to do a kan.
113
+ self .action .label = "kan"
114
+ self .action .add_class ("action_kakan" ) # We don't know which kan it is, so we just use kakan as a placeholder.
115
+ self .pai .update (TILE_2_UNICODE_ART_RICH ["?" ])
116
+ self .vertical_rule .update (EMPTY_VERTICAL_RULE )
117
+ for i in range (3 ):
118
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH ["?" ])
119
+ elif recommand [0 ] in ['reach' , 'hora' , 'ryukyoku' , 'none' ]:
120
+ self .action .label = recommand [0 ]
121
+ self .action .add_class ("action_" + recommand [0 ])
122
+ self .pai .update (TILE_2_UNICODE_ART_RICH ["?" ])
123
+ self .vertical_rule .update (EMPTY_VERTICAL_RULE )
124
+ for i in range (3 ):
125
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH ["?" ])
126
+ elif recommand [0 ] in ['nukidora' ]:
127
+ self .action .label = "nukidora"
128
+ self .action .add_class ("action_nukidora" )
129
+ self .pai .update (TILE_2_UNICODE_ART_RICH ["N" ])
130
+ self .vertical_rule .update (EMPTY_VERTICAL_RULE )
131
+ for i in range (3 ):
132
+ self .consumes [i ].update (TILE_2_UNICODE_ART_RICH ["?" ])
133
+ pass
134
+
135
+
44
136
class FlowScreen (Screen ):
45
137
46
138
BINDINGS = [
@@ -61,14 +153,16 @@ def __init__(self, flow_id, *args, **kwargs) -> None:
61
153
62
154
def compose (self ) -> ComposeResult :
63
155
"""Called to add widgets to the app."""
64
- liqi_log_container = ScrollableContainer (Pretty (self .app .liqi_msg_dict [self .flow_id ], id = "liqi_log" ), id = "liqi_log_container" )
156
+ # liqi_log_container = ScrollableContainer(Pretty(self.app.liqi_msg_dict[self.flow_id], id="liqi_log"), id="liqi_log_container")
157
+ recommandations = [Recommandation (i , classes = "recommandations" , id = "recommandation_" + str (i )) for i in range (3 )]
158
+ recommandations_container = Vertical (* recommandations , id = "recommandations_container" )
65
159
mjai_log_container = ScrollableContainer (Pretty (self .app .mjai_msg_dict [self .flow_id ], id = "mjai_log" ), id = "mjai_log_container" )
66
- log_container = Horizontal (liqi_log_container , mjai_log_container , id = "log_container" )
67
- liqi_log_container .border_title = "LiqiProto "
160
+ log_container = Horizontal (recommandations_container , mjai_log_container , id = "log_container" )
161
+ recommandations_container .border_title = "Recommandations "
68
162
mjai_log_container .border_title = "Mjai"
69
163
tehai_labels = [Label (TILE_2_UNICODE_ART_RICH ["?" ], id = "tehai_" + str (i )) for i in range (13 )]
70
164
tehai_value_labels = [Label (HAI_VALUE [40 ], id = "tehai_value_" + str (i )) for i in range (13 )]
71
- tehai_rule = Label (VERTICLE_RULE , id = "tehai_rule" )
165
+ tehai_rule = Label (VERTICAL_RULE , id = "tehai_rule" )
72
166
tsumohai_label = Label (TILE_2_UNICODE_ART_RICH ["?" ], id = "tsumohai" )
73
167
tsumohai_value_label = Label (HAI_VALUE [40 ], id = "tsumohai_value" )
74
168
tehai_container = Horizontal (id = "tehai_container" )
@@ -103,25 +197,26 @@ def compose(self) -> ComposeResult:
103
197
yield bottom_container
104
198
105
199
def on_mount (self ) -> None :
106
- self .liqi_log = self .query_one ("#liqi_log" )
200
+ # self.liqi_log = self.query_one("#liqi_log")
107
201
self .mjai_log = self .query_one ("#mjai_log" )
108
202
self .akagi_action = self .query_one ("#akagi_action" )
109
203
self .akagi_pai = self .query_one ("#akagi_pai" )
110
204
self .pai_unicode_art = self .query_one ("#pai_unicode_art" )
111
205
self .vertical_rule = self .query_one ("#vertical_rule" )
112
206
self .consumed_pais = [self .query_one ("#consumed_" + str (i )) for i in range (3 )]
113
207
self .akagi_container = self .query_one ("#akagi_container" )
114
- self .liqi_log .update (self .app .liqi_msg_dict [self .flow_id ])
208
+ # self.liqi_log.update(self.app.liqi_msg_dict[self.flow_id])
115
209
self .mjai_log .update (self .app .mjai_msg_dict [self .flow_id ])
116
- self .liqi_log_container = self .query_one ("#liqi_log_container" )
210
+ # self.liqi_log_container = self.query_one("#liqi_log_container")
211
+ self .recommandations_container = self .query_one ("#recommandations_container" )
117
212
self .mjai_log_container = self .query_one ("#mjai_log_container" )
118
213
self .tehai_labels = [self .query_one ("#tehai_" + str (i )) for i in range (13 )]
119
214
self .tehai_value_labels = [self .query_one ("#tehai_value_" + str (i )) for i in range (13 )]
120
215
self .tehai_rule = self .query_one ("#tehai_rule" )
121
216
self .tsumohai_label = self .query_one ("#tsumohai" )
122
217
self .tsumohai_value_label = self .query_one ("#tsumohai_value" )
123
218
self .tehai_container = self .query_one ("#tehai_container" )
124
- self .liqi_log_container .scroll_end (animate = False )
219
+ # self.liqi_log_container.scroll_end(animate=False)
125
220
self .mjai_log_container .scroll_end (animate = False )
126
221
self .liqi_msg_idx = len (self .app .liqi_msg_dict [self .flow_id ])
127
222
self .mjai_msg_idx = len (self .app .mjai_msg_dict [self .flow_id ])
@@ -141,8 +236,8 @@ def refresh_log(self) -> None:
141
236
# Yes I know this is stupid
142
237
try :
143
238
if self .liqi_msg_idx < len (self .app .liqi_msg_dict [self .flow_id ]):
144
- self .liqi_log .update (self .app .liqi_msg_dict [self .flow_id ][- 1 ])
145
- self .liqi_log_container .scroll_end (animate = False )
239
+ # self.liqi_log.update(self.app.liqi_msg_dict[self.flow_id][-1])
240
+ # self.liqi_log_container.scroll_end(animate=False)
146
241
self .liqi_msg_idx += 1
147
242
liqi_msg = self .app .liqi_msg_dict [self .flow_id ][- 1 ]
148
243
if liqi_msg ['type' ] == MsgType .Notify :
@@ -218,15 +313,22 @@ def refresh_log(self) -> None:
218
313
if "pai" in latest_mjai_msg :
219
314
self .pai_unicode_art .update (TILE_2_UNICODE_ART_RICH [latest_mjai_msg ["pai" ]])
220
315
for i , c in enumerate (latest_mjai_msg ["consumed" ]):
316
+ if i >= 3 :
317
+ # ankan
318
+ self .pai_unicode_art .update (TILE_2_UNICODE_ART_RICH [c ])
319
+ continue
221
320
self .consumed_pais [i ].update (TILE_2_UNICODE_ART_RICH [c ])
222
- self .vertical_rule .update (VERTICLE_RULE )
321
+ self .vertical_rule .update (VERTICAL_RULE )
223
322
elif "pai" in latest_mjai_msg :
224
323
self .consume_ids = []
225
324
self .akagi_pai .label = str (latest_mjai_msg ["pai" ])
226
325
self .pai_unicode_art .update (TILE_2_UNICODE_ART_RICH [latest_mjai_msg ["pai" ]])
227
326
else :
228
327
self .akagi_pai .label = "None"
229
328
self .pai_unicode_art .update (TILE_2_UNICODE_ART_RICH ["?" ])
329
+ for recommandation in self .recommandations_container .children :
330
+ recommandation .update (latest_mjai_msg , player_state )
331
+
230
332
# Action
231
333
logger .info (f"Current tehai: { tehai } " )
232
334
logger .info (f"Current tsumohai: { tsumohai } " )
@@ -249,7 +351,13 @@ def checkbox_autoplay_changed(self, event: Checkbox.Changed) -> None:
249
351
pass
250
352
251
353
def redo_action (self ) -> None :
252
- self .action .mjai2action (self .app .mjai_msg_dict [self .flow_id ][- 1 ], self .tehai , self .tsumohai , None , True )
354
+ try :
355
+ self .action .mjai2action (self .app .mjai_msg_dict [self .flow_id ][- 1 ], self .tehai , self .tsumohai , None , True )
356
+ except Exception as e :
357
+ logger .error (e )
358
+ if self .dahai_verfication_job is not None :
359
+ self .dahai_verfication_job .stop ()
360
+ self .dahai_verfication_job = None
253
361
254
362
def autoplay (self ) -> None :
255
363
isliqi = self .isLiqi
0 commit comments