diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 75420a0..7e38cfc 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -474,7 +474,7 @@ class BadukPanWidget(Widget): self.gridpos_y[move.coords[1]], self.stone_size - 1.2, s, - s + 15, + s + 12, ), width=dp(1.2), ) @@ -524,9 +524,9 @@ class BadukPanWidget(Widget): stone_size = self.stone_size * sizefac Color(1, 1, 1, 1) - Rectangle( - pos=(board_coords[0] - stone_size, board_coords[1] - stone_size), - size=(2 * stone_size, 2 * stone_size), + Rectangle( # not sure why the -1 here, but seems to center better + pos=(board_coords[0] - stone_size - 1, board_coords[1] - stone_size), + size=(2 * stone_size + 1, 2 * stone_size + 1), source=f"img/{move_player}_stone.png", ) Color(*STONE_TEXT_COLORS[move_player]) diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index 678759c..1cd1521 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -205,7 +205,7 @@ class IMETextField(MDTextField): self._imo_cursor = self.cursor -class I18NSpinner(Spinner): +class KeyValueSpinner(Spinner): __events__ = ["on_select"] sync_height_frac = NumericProperty(1.0) value_refs = ListProperty() @@ -214,9 +214,8 @@ class I18NSpinner(Spinner): def __init__(self, **kwargs): super().__init__(**kwargs) - self.bind(size=self.update_dropdown_props, pos=self.update_dropdown_props, value_refs=self.i18n_values) - self.i18n_values() - MDApp.get_running_app().bind(language=self.i18n_values) + self.build_values() + self.bind(size=self.update_dropdown_props, pos=self.update_dropdown_props, value_refs=self.build_values) @property def selected(self): @@ -245,9 +244,8 @@ class I18NSpinner(Spinner): except (ValueError, IndexError): pass - def i18n_values(self, *_args): - if self.value_refs: - self.values = [i18n._(ref) for ref in self.value_refs] + def build_values(self, *_args): + if self.value_refs and self.values: self.text = self.values[self.selected_index] self.font_name = i18n.font_name self.update_dropdown_props() @@ -269,6 +267,22 @@ class I18NSpinner(Spinner): item.font_name = self.font_name +class I18NSpinner(KeyValueSpinner): + __events__ = ["on_select"] + sync_height_frac = NumericProperty(1.0) + value_refs = ListProperty() + selected_index = NumericProperty(0) + font_name = StringProperty(DEFAULT_FONT) + + def __init__(self, **kwargs): + super().__init__(**kwargs) + MDApp.get_running_app().bind(language=self.build_values) + + def build_values(self, *_args): + self.values = [i18n._(ref) for ref in self.value_refs] + super().build_values() + + class PlayerSetup(MDBoxLayout): player = OptionProperty("B", options=["B", "W"]) mode = StringProperty("") diff --git a/katrain/gui/popups.py b/katrain/gui/popups.py index 8b776d0..43a108c 100644 --- a/katrain/gui/popups.py +++ b/katrain/gui/popups.py @@ -386,6 +386,18 @@ class ConfigPopup(QuickConfigGui): super().build_and_set_properties() def check_models(self, *args): + def find_description(path): + file = os.path.split(path)[1] + file_to_desc = { + re.match(r".*/([^/]+)", model)[1].replace(".zip", ".bin.gz"): desc + for mods in [self.MODELS, self.MODEL_DESC] + for desc, model in mods.items() + } + if file in file_to_desc: + return f"{file_to_desc[file]} - {path}" + else: + return path + done = set() model_files = [] for path in self.paths + [self.model_path.text]: @@ -407,13 +419,28 @@ class ConfigPopup(QuickConfigGui): if files and path not in self.paths: self.paths.append(path) # persistent on paths with models found model_files += files + + model_files = sorted([(find_description(path), path) for path in model_files]) models_available_msg = i18n._("models available").format(num=len(model_files)) - self.model_files.values = [models_available_msg] + model_files + self.model_files.values = [models_available_msg] + [desc for desc, path in model_files] + self.model_files.value_keys = [""] + [path for desc, path in model_files] self.model_files.text = models_available_msg def check_katas(self, *args): + def find_description(path): + file = os.path.split(path)[1].replace(".exe", "") + file_to_desc = { + re.match(r".*/([^/]+)", kg)[1].replace(".zip", ""): desc + for _, kgs in self.KATAGOS.items() + for desc, kg in kgs.items() + } + if file in file_to_desc: + return f"{file_to_desc[file]} - {path}" + else: + return path + done = set() - model_files = [] + kata_files = [] for path in self.katago_paths + [self.katago_path.text]: path = path.rstrip("/\\") if path.startswith("katrain"): @@ -433,34 +460,43 @@ class ConfigPopup(QuickConfigGui): ] if files and path not in self.paths: self.paths.append(path) # persistent on paths with models found - model_files += files - katas_available_msg = i18n._("katago binaries available").format(num=len(model_files)) - self.katago_files.values = [katas_available_msg, i18n._("default katago option")] + sorted( - model_files, key=lambda f: "bs29" in f - ) + kata_files += files + + kata_files = [(path, find_description(path)) for path in sorted(kata_files, key=lambda f: "bs29" in f)] + katas_available_msg = i18n._("katago binaries available").format(num=len(kata_files)) + self.katago_files.values = [katas_available_msg, i18n._("default katago option")] + [ + desc for path, desc in kata_files + ] + self.katago_files.value_keys = ["", ""] + [path for path, desc in kata_files] self.katago_files.text = katas_available_msg MODELS = { - "latest 20b": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170e-b20c256x2-s5303129600-d1228401921.bin.gz", - "latest 30b": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170-b30c320x2-s4824661760-d1229536699.bin.gz", - "latest 40b": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170-b40c256x2-s5095420928-d1229425124.bin.gz", + "Latest 20 block model": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170e-b20c256x2-s5303129600-d1228401921.bin.gz", + "Latest 30 block model": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170-b30c320x2-s4824661760-d1229536699.bin.gz", + "Latest 40 block model": "https://github.com/lightvector/KataGo/releases/download/v1.4.5/g170-b40c256x2-s5095420928-d1229425124.bin.gz", + } + MODEL_DESC = { + "Fat 40 block model": "https://d3dndmfyhecmj0.cloudfront.net/g170/neuralnets/g170e-b40c384x2-s2348692992-d1229892979.zip", + "Latest 15 block model": "https://d3dndmfyhecmj0.cloudfront.net/g170/neuralnets/g170e-b15c192-s1672170752-d466197061.bin.gz", } KATAGOS = { "win": { "OpenCL v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-opencl-windows-x64.zip", - # "CUDA v1.6.1 (New NVIDIA cards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-cuda10.2-windows-x64.zip", "Eigen AVX2 (Modern CPUs) v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-cpu-eigen-avx2-windows-x64.zip", "Eigen (CPU, Non-optimized) v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-cpu-eigen-windows-x64.zip", "OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-windows-x64.zip", }, "linux": { "OpenCL v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-opencl-linux-x64.zip", - # "CUDA v1.6.1 (New NVIDIA cards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-cuda10.2-linux-x64.zip", "Eigen AVX2 (Modern CPUs) v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-cpu-eigen-avx2-linux-x64.zip", "Eigen (CPU, Non-optimized) v1.6.1": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-cpu-eigen-linux-x64.zip", "OpenCL v1.6.1 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1%2Bbs29/katago-v1.6.1+bs29-gpu-opencl-linux-x64.zip", }, + "just-descriptions": { + "CUDA v1.6.1 (Windows)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-cuda10.2-windows-x64.zip", + "CUDA v1.6.1 (Linux)": "https://github.com/lightvector/KataGo/releases/download/v1.6.1/katago-v1.6.1-gpu-cuda10.2-linux-x64.zip", + }, } def download_models(self, *_largs): diff --git a/katrain/popups.kv b/katrain/popups.kv index 5522888..c9c5265 100644 --- a/katrain/popups.kv +++ b/katrain/popups.kv @@ -109,12 +109,16 @@ on_press: root.download_katas() size_hint_y: 0.7 AnchorLayout: - Spinner: + KeyValueSpinner: id: katago_files text: '' - on_text: - if self.text and self.text == self.values[1]: katago_path.text = '' - elif self.text and self.text != self.values[0]: katago_path.text = args[1] + text_autoupdate: True + -text_size: self.width, None + -halign: 'center' + -shorten: True + -shorten_from: 'right' + on_select: + if self.selected_index != 0: katago_path.text = self.value_keys[self.selected_index] size_hint_y: 0.7 sync_height_frac: 1.0 -font_size: self.height * 0.5 @@ -140,10 +144,16 @@ on_press: root.download_models() size_hint_y: 0.7 AnchorLayout: - Spinner: + KeyValueSpinner: id: model_files text: '' - on_text: if self.text and self.text != self.values[0]: model_path.text = args[1] + text_autoupdate: True + -text_size: self.width, None + -halign: 'center' + -shorten: True + -shorten_from: 'right' + on_select: + if self.selected_index != 0: model_path.text = self.value_keys[self.selected_index] size_hint_y: 0.7 sync_height_frac: 1.0 -font_size: self.height * 0.5