Skip to content

Commit d7150a3

Browse files
author
shinkuan
committed
Add Recommandation
1 parent 097ba4e commit d7150a3

File tree

3 files changed

+159
-17
lines changed

3 files changed

+159
-17
lines changed

client.py

+123-15
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
from textual.screen import Screen
2222
from textual.widgets import (Button, Checkbox, Footer, Header, Input, Label,
2323
LoadingIndicator, Log, Markdown, Pretty, Rule,
24-
Static)
24+
Digits, Static)
2525

2626
from action import Action
2727
from liqi import LiqiProto, MsgType
2828
from majsoul2mjai import MajsoulBridge
2929
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)
3232

3333
submission = 'players/bot.zip'
3434
PORT_NUM = 28680
@@ -41,6 +41,98 @@
4141
ENABLE_PLAYWRIGHT = settings["Playwright"]["enable"]
4242

4343

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+
44136
class FlowScreen(Screen):
45137

46138
BINDINGS = [
@@ -61,14 +153,16 @@ def __init__(self, flow_id, *args, **kwargs) -> None:
61153

62154
def compose(self) -> ComposeResult:
63155
"""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")
65159
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"
68162
mjai_log_container.border_title = "Mjai"
69163
tehai_labels = [Label(TILE_2_UNICODE_ART_RICH["?"], id="tehai_"+str(i)) for i in range(13)]
70164
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")
72166
tsumohai_label = Label(TILE_2_UNICODE_ART_RICH["?"], id="tsumohai")
73167
tsumohai_value_label = Label(HAI_VALUE[40], id="tsumohai_value")
74168
tehai_container = Horizontal(id="tehai_container")
@@ -103,25 +197,26 @@ def compose(self) -> ComposeResult:
103197
yield bottom_container
104198

105199
def on_mount(self) -> None:
106-
self.liqi_log = self.query_one("#liqi_log")
200+
# self.liqi_log = self.query_one("#liqi_log")
107201
self.mjai_log = self.query_one("#mjai_log")
108202
self.akagi_action = self.query_one("#akagi_action")
109203
self.akagi_pai = self.query_one("#akagi_pai")
110204
self.pai_unicode_art = self.query_one("#pai_unicode_art")
111205
self.vertical_rule = self.query_one("#vertical_rule")
112206
self.consumed_pais = [self.query_one("#consumed_"+str(i)) for i in range(3)]
113207
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])
115209
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")
117212
self.mjai_log_container = self.query_one("#mjai_log_container")
118213
self.tehai_labels = [self.query_one("#tehai_"+str(i)) for i in range(13)]
119214
self.tehai_value_labels = [self.query_one("#tehai_value_"+str(i)) for i in range(13)]
120215
self.tehai_rule = self.query_one("#tehai_rule")
121216
self.tsumohai_label = self.query_one("#tsumohai")
122217
self.tsumohai_value_label = self.query_one("#tsumohai_value")
123218
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)
125220
self.mjai_log_container.scroll_end(animate=False)
126221
self.liqi_msg_idx = len(self.app.liqi_msg_dict[self.flow_id])
127222
self.mjai_msg_idx = len(self.app.mjai_msg_dict[self.flow_id])
@@ -141,8 +236,8 @@ def refresh_log(self) -> None:
141236
# Yes I know this is stupid
142237
try:
143238
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)
146241
self.liqi_msg_idx += 1
147242
liqi_msg = self.app.liqi_msg_dict[self.flow_id][-1]
148243
if liqi_msg['type'] == MsgType.Notify:
@@ -218,15 +313,22 @@ def refresh_log(self) -> None:
218313
if "pai" in latest_mjai_msg:
219314
self.pai_unicode_art.update(TILE_2_UNICODE_ART_RICH[latest_mjai_msg["pai"]])
220315
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
221320
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)
223322
elif "pai" in latest_mjai_msg:
224323
self.consume_ids = []
225324
self.akagi_pai.label = str(latest_mjai_msg["pai"])
226325
self.pai_unicode_art.update(TILE_2_UNICODE_ART_RICH[latest_mjai_msg["pai"]])
227326
else:
228327
self.akagi_pai.label = "None"
229328
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+
230332
# Action
231333
logger.info(f"Current tehai: {tehai}")
232334
logger.info(f"Current tsumohai: {tsumohai}")
@@ -249,7 +351,13 @@ def checkbox_autoplay_changed(self, event: Checkbox.Changed) -> None:
249351
pass
250352

251353
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
253361

254362
def autoplay(self) -> None:
255363
isliqi = self.isLiqi

client.tcss

+27-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,39 @@
2020
}
2121

2222
#mjai_log_container {
23-
width: 1fr;
23+
width: 2fr;
24+
height: 1fr;
25+
border: round $accent;
26+
border-title-align: center;
27+
align: right top;
28+
padding: 1;
29+
}
30+
31+
#recommandations_container {
32+
width: 3fr;
2433
height: 1fr;
2534
border: round $accent;
2635
border-title-align: center;
2736
align: right top;
2837
padding: 1;
2938
}
3039

40+
.recommand_button {
41+
height: 1fr;
42+
align: center top;
43+
min-width: 10;
44+
}
45+
46+
.action_container {
47+
min-width: 45;
48+
height: 5;
49+
align: left top;
50+
}
51+
52+
.recommand_digit {
53+
margin: 1 1;
54+
}
55+
3156
$chi: #00ff80;
3257
$chi-lighten-1: #3f9;
3358
$chi-lighten-2: #66ffb3;
@@ -41,6 +66,7 @@ Button.action_chi {
4166
color: $text;
4267
border-top: tall $chi-lighten-2;
4368
border-bottom: tall $chi-darken-3;
69+
min-width: 10;
4470
}
4571

4672
Button.action_chi:hover {

tileUnicode.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
TILE_LIST = [
2+
"1m", "2m", "3m", "4m", "5m", "6m", "7m", "8m", "9m",
3+
"1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p",
4+
"1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
5+
"E", "S", "W", "N", "P", "F", "C",
6+
"5mr", "5pr", "5sr"
7+
]
8+
19
TILE_2_UNICODE = {
210
'5mr':'🀋',
311
'1m': '🀇',
@@ -500,7 +508,7 @@
500508

501509
}
502510

503-
VERTICLE_RULE = """║
511+
VERTICAL_RULE = """║
504512
505513
506514

0 commit comments

Comments
 (0)