From 2499488a203aac0cd4c37ef2412188b531527a43 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Wed, 9 Dec 2020 22:15:14 +0100 Subject: [PATCH] hints for player names, flake8, rankgraph ded --- i18n.py | 4 +- katrain/__main__.py | 10 +- katrain/core/ai.py | 6 +- katrain/core/game.py | 1 - katrain/core/sgf_parser.py | 4 +- katrain/core/utils.py | 2 +- katrain/gui/badukpan.py | 11 +- katrain/gui/controlspanel.py | 2 +- katrain/gui/kivyutils.py | 8 +- katrain/gui/popups.py | 2 +- katrain/gui/widgets/__init__.py | 4 +- katrain/gui/widgets/filebrowser.py | 15 +- katrain/gui/widgets/graph.py | 180 +----------------- katrain/gui/widgets/movetree.py | 8 +- katrain/gui/widgets/selection_slider.py | 4 +- .../i18n/locales/cn/LC_MESSAGES/katrain.mo | Bin 14219 -> 14216 bytes .../i18n/locales/cn/LC_MESSAGES/katrain.po | 7 + .../i18n/locales/de/LC_MESSAGES/katrain.mo | Bin 16370 -> 16376 bytes .../i18n/locales/de/LC_MESSAGES/katrain.po | 7 + .../i18n/locales/en/LC_MESSAGES/katrain.mo | Bin 15533 -> 15651 bytes .../i18n/locales/en/LC_MESSAGES/katrain.po | 8 + .../i18n/locales/es/LC_MESSAGES/katrain.mo | Bin 15766 -> 15772 bytes .../i18n/locales/es/LC_MESSAGES/katrain.po | 7 + .../i18n/locales/fr/LC_MESSAGES/katrain.mo | Bin 17473 -> 17479 bytes .../i18n/locales/fr/LC_MESSAGES/katrain.po | 8 + .../i18n/locales/jp/LC_MESSAGES/katrain.mo | Bin 17887 -> 17880 bytes .../i18n/locales/jp/LC_MESSAGES/katrain.po | 8 + .../i18n/locales/ko/LC_MESSAGES/katrain.mo | Bin 17406 -> 17412 bytes .../i18n/locales/ko/LC_MESSAGES/katrain.po | 7 + .../i18n/locales/ru/LC_MESSAGES/katrain.mo | Bin 22196 -> 22202 bytes .../i18n/locales/ru/LC_MESSAGES/katrain.po | 7 + katrain/popups.kv | 2 + setup.py | 2 +- tests/test_board.py | 2 +- tests/test_parser.py | 5 +- 35 files changed, 100 insertions(+), 231 deletions(-) diff --git a/i18n.py b/i18n.py index 51288e0..9adf47b 100644 --- a/i18n.py +++ b/i18n.py @@ -27,7 +27,7 @@ for lang in locales: pofile[lang] = os.path.join(localedir, lang, "LC_MESSAGES", "katrain.po") po[lang] = polib.pofile(pofile[lang]) for entry in po[lang].translated_entries(): - if "TODO" in entry.comment and not "DEPRECATED" in entry.comment: + if "TODO" in entry.comment and "DEPRECATED" not in entry.comment: todos[lang].append(entry) strings_to_langs[entry.msgid][lang] = entry strings_to_keys[entry.msgid][lang] = set(re.findall("{.*?}", entry.msgstr)) @@ -75,7 +75,7 @@ for lang in locales: for msgid, lang_entries in strings_to_langs.items(): if lang in lang_entries and "TODO" in lang_entries[lang].comment: - if any(e.msgstr == lang_entries[lang].msgstr for l, e in lang_entries.items() if l != lang): + if any(e.msgstr == lang_entries[lang].msgstr for ll, e in lang_entries.items() if ll != lang): todo_comment = ( f"TODO - {lang_entries[DEFAULT_LANG].comment}" if lang_entries[DEFAULT_LANG].comment else "TODO" ) # update todo diff --git a/katrain/__main__.py b/katrain/__main__.py index e4671a4..e4c1345 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -74,7 +74,7 @@ from katrain.core.game import Game, IllegalMoveException, KaTrainSGF from katrain.core.sgf_parser import Move, ParseError from katrain.gui.kivyutils import * from katrain.gui.popups import ConfigPopup, LoadSGFPopup, NewGamePopup, ConfigAIPopup -from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL, LIGHTGREY +from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL from katrain.gui.widgets import * from katrain.gui.badukpan import AnalysisControls, BadukPanControls, BadukPanWidget from katrain.gui.controlspanel import ControlsPanel @@ -108,14 +108,14 @@ class KaTrainGui(Screen, KaTrainBase): super().log(message, level) if level == OUTPUT_KATAGO_STDERR and "ERROR" not in self.controls.status.text: if "starting" in message.lower(): - self.controls.set_status(f"KataGo engine starting...", STATUS_INFO) + self.controls.set_status("KataGo engine starting...", STATUS_INFO) if message.startswith("Tuning"): self.controls.set_status( - f"KataGo is tuning settings for first startup, please wait." + message, STATUS_INFO + "KataGo is tuning settings for first startup, please wait." + message, STATUS_INFO ) return if "ready" in message.lower(): - self.controls.set_status(f"KataGo engine ready.", STATUS_INFO) + self.controls.set_status("KataGo engine ready.", STATUS_INFO) if ( level == OUTPUT_ERROR or (level == OUTPUT_KATAGO_STDERR and "error" in message.lower() and "tuning" not in message.lower()) @@ -450,7 +450,7 @@ class KaTrainGui(Screen, KaTrainBase): def load_sgf_from_clipboard(self): clipboard = Clipboard.paste() if not clipboard: - self.controls.set_status(f"Ctrl-V pressed but clipboard is empty.", STATUS_INFO) + self.controls.set_status("Ctrl-V pressed but clipboard is empty.", STATUS_INFO) return url_match = re.match(r"(?Phttps?://[^\s]+)", clipboard) diff --git a/katrain/core/ai.py b/katrain/core/ai.py index 8c7da85..457d4a1 100644 --- a/katrain/core/ai.py +++ b/katrain/core/ai.py @@ -203,7 +203,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, game, cn, {"playoutDoublingAdvantage": pda, "playoutDoublingAdvantagePla": "BLACK"} ) if not handicap_analysis: - game.katrain.log(f"Error getting handicap-based move", OUTPUT_ERROR) + game.katrain.log("Error getting handicap-based move", OUTPUT_ERROR) ai_mode = AI_DEFAULT while not cn.analysis_complete: @@ -225,7 +225,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, ai_mode in [AI_LOCAL, AI_TENUKI] and not (cn.move and cn.move.coords) ): ai_mode = AI_WEIGHTED - ai_thoughts += f"Strategy override, using policy-weighted strategy instead. " + ai_thoughts += "Strategy override, using policy-weighted strategy instead. " ai_settings = {"pick_override": 0.9, "weaken_fac": 1, "lower_bound": 0.02} if top_5_pass: @@ -336,7 +336,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move, AI_HANDICAP, ]: # don't play suicidal to balance score aimove = top_cand - ai_thoughts += f"Top move is pass, so passing regardless of strategy. " + ai_thoughts += "Top move is pass, so passing regardless of strategy. " else: if ai_mode == AI_JIGO: sign = cn.player_sign(cn.next_player) diff --git a/katrain/core/game.py b/katrain/core/game.py index 078c7a3..efc19cb 100644 --- a/katrain/core/game.py +++ b/katrain/core/game.py @@ -10,7 +10,6 @@ from kivy.clock import Clock from katrain.core.constants import ( ANALYSIS_FORMAT_VERSION, - HOMEPAGE, OUTPUT_DEBUG, OUTPUT_INFO, PLAYER_AI, diff --git a/katrain/core/sgf_parser.py b/katrain/core/sgf_parser.py index 5b03656..bf540ce 100644 --- a/katrain/core/sgf_parser.py +++ b/katrain/core/sgf_parser.py @@ -280,7 +280,7 @@ class SGFNode: @property def next_player(self): """Returns player to move""" - if "B" in self.properties or ("AB" in self.properties and not "W" in self.properties): # root or black moved + if "B" in self.properties or ("AB" in self.properties and "W" not in self.properties): # root or black moved return "W" else: return "B" @@ -288,7 +288,7 @@ class SGFNode: @property def player(self): """Returns player that moved last. nb root is considered white played if no handicap stones are placed""" - if "B" in self.properties or ("AB" in self.properties and not "W" in self.properties): + if "B" in self.properties or ("AB" in self.properties and "W" not in self.properties): return "B" else: return "W" diff --git a/katrain/core/utils.py b/katrain/core/utils.py index 044aa92..048ebd2 100644 --- a/katrain/core/utils.py +++ b/katrain/core/utils.py @@ -5,7 +5,7 @@ from typing import List, Tuple, TypeVar try: import importlib.resources as pkg_resources -except: +except ImportError: import importlib_resources as pkg_resources T = TypeVar("T") diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 2b31443..e41f318 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -1,4 +1,3 @@ -import copy import math import random import time @@ -33,7 +32,7 @@ from katrain.core.constants import ( from katrain.core.game import Move from katrain.core.lang import i18n from katrain.core.utils import evaluation_class, format_visits, var_to_grid -from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text, cached_texture +from katrain.gui.kivyutils import draw_circle, draw_text, cached_texture from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup from katrain.gui.style import * @@ -209,7 +208,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize), size=(2 * evalsize, 2 * evalsize), - texture=cached_texture(f"img/dot.png"), + texture=cached_texture("img/dot.png"), ) if innercol: Color(*innercol) @@ -217,7 +216,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - inner_size, self.gridpos_y[y] - inner_size), size=(2 * inner_size, 2 * inner_size), - texture=cached_texture(f"img/inner.png"), + texture=cached_texture("img/inner.png"), ) def eval_color(self, points_lost, show_dots_for_class: List[bool] = None) -> Optional[List[float]]: @@ -504,7 +503,7 @@ class BadukPanWidget(Widget): katrain = self.katrain game_ended = katrain.game.end_result current_node = katrain.game.current_node - player, next_player = current_node.player, current_node.next_player + next_player = current_node.next_player board_size_x, board_size_y = katrain.game.board_size if len(self.gridpos_x) < board_size_x or len(self.gridpos_y) < board_size_y: @@ -580,7 +579,7 @@ class BadukPanWidget(Widget): ) if text_on and top_moves_show: # TODO: faster if not sized? keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33} - player_sign = current_node.player_sign(current_node.next_player) + player_sign = current_node.player_sign(next_player) if len(top_moves_show) == 1: fmt = "[size={size:.0f}]{" + top_moves_show[0] + "}[/size]" else: diff --git a/katrain/gui/controlspanel.py b/katrain/gui/controlspanel.py index c848400..1fe8d9c 100644 --- a/katrain/gui/controlspanel.py +++ b/katrain/gui/controlspanel.py @@ -135,7 +135,7 @@ class ControlsPanel(BoxLayout): lock_ai = katrain.config("trainer/lock_ai") and katrain.play_analyze_mode == MODE_PLAY details = self.info.detailed and not lock_ai info = "" - if current_node.move or current_node.is_root: + if move or current_node.is_root: info = self.active_comment_node.comment( teach=katrain.players_info[self.active_comment_node.player].being_taught, details=details ) diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index dd86253..b37e3cf 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -1,6 +1,3 @@ -import functools - -from kivy.cache import Cache from kivy.clock import Clock from kivy.core.image import Image from kivy.core.text import Label as CoreLabel @@ -16,13 +13,12 @@ from kivy.properties import ( StringProperty, ) from kivy.resources import resource_find -from kivy.uix.behaviors import ButtonBehavior, FocusBehavior, ToggleButtonBehavior +from kivy.uix.behaviors import ButtonBehavior, ToggleButtonBehavior from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.label import Label from kivy.uix.scrollview import ScrollView from kivy.uix.spinner import Spinner -from kivy.uix.textinput import TextInput from kivy.uix.widget import Widget from kivymd.app import MDApp from kivymd.uix.behaviors import CircularRippleBehavior, RectangularRippleBehavior @@ -229,7 +225,7 @@ class KeyValueSpinner(Spinner): def input_value(self): try: return self.value_refs[self.selected_index] - except: + except KeyError: return "" @property diff --git a/katrain/gui/popups.py b/katrain/gui/popups.py index ccbf738..4c24bbb 100644 --- a/katrain/gui/popups.py +++ b/katrain/gui/popups.py @@ -207,7 +207,7 @@ class QuickConfigGui(MDBoxLayout): selected = 0 try: selected = widget.value_refs.index(value) - except: + except: # noqa: E722 pass widget.text = widget.values[selected] else: diff --git a/katrain/gui/widgets/__init__.py b/katrain/gui/widgets/__init__.py index e5bec48..9bd55b8 100644 --- a/katrain/gui/widgets/__init__.py +++ b/katrain/gui/widgets/__init__.py @@ -1,6 +1,6 @@ from katrain.gui.widgets.filebrowser import I18NFileBrowser -from katrain.gui.widgets.graph import RankGraph, ScoreGraph +from katrain.gui.widgets.graph import ScoreGraph from katrain.gui.widgets.movetree import MoveTree from katrain.gui.widgets.selection_slider import SelectionSlider -__all__ = ["ScoreGraph", "RankGraph", "MoveTree", "I18NFileBrowser", "SelectionSlider"] +__all__ = ["ScoreGraph", "MoveTree", "I18NFileBrowser", "SelectionSlider"] diff --git a/katrain/gui/widgets/filebrowser.py b/katrain/gui/widgets/filebrowser.py index 64891dd..fb65e80 100644 --- a/katrain/gui/widgets/filebrowser.py +++ b/katrain/gui/widgets/filebrowser.py @@ -38,7 +38,6 @@ a shortcut to the Documents directory added to the favorites bar:: :align: right """ import string -import warnings from functools import partial from os import walk from os.path import dirname, expanduser, getmtime, isdir, join, sep @@ -81,27 +80,25 @@ def get_drives(): drives = [] if platform == "win": bitmask = windll.kernel32.GetLogicalDrives() - GetVolumeInformationW = windll.kernel32.GetVolumeInformationW for letter in string.ascii_uppercase: if bitmask & 1: name = create_unicode_buffer(64) # get name of the drive - drive = letter + u":" - res = GetVolumeInformationW(drive + sep, name, 64, None, None, None, None, 0) + drive = letter + ":" if isdir(drive): drives.append((drive, name.value)) bitmask >>= 1 elif platform == "linux": drives.append((sep, sep)) - drives.append((expanduser(u"~"), "~/")) - places = (sep + u"mnt", sep + u"media") + drives.append((expanduser("~"), "~/")) + places = (sep + "mnt", sep + "media") for place in places: if isdir(place): for directory in next(walk(place))[1]: drives.append((place + sep + directory, directory)) elif platform == "macosx" or platform == "ios": - drives.append((expanduser(u"~"), "~/")) - vol = sep + u"Volume" + drives.append((expanduser("~"), "~/")) + vol = sep + "Volume" if isdir(vol): for drive in next(walk(vol))[1]: drives.append((vol + sep + drive, drive)) @@ -154,7 +151,7 @@ Builder.load_string( layout: layout I18NFileChooserListLayout: id: layout - controller: root + controller: root """ ) Config.set("kivy", "log_level", log_level) diff --git a/katrain/gui/widgets/graph.py b/katrain/gui/widgets/graph.py index c7c1507..6351abc 100644 --- a/katrain/gui/widgets/graph.py +++ b/katrain/gui/widgets/graph.py @@ -7,9 +7,6 @@ from kivy.properties import BooleanProperty, Clock, ListProperty, NumericPropert from kivy.uix.widget import Widget from kivymd.app import MDApp -from katrain.core.constants import OUTPUT_ERROR -from katrain.core.lang import rank_label - class Graph(Widget): marker_font_size = NumericProperty(0) @@ -128,11 +125,11 @@ class ScoreGraph(Graph): xscale = self.width / max(len(score_values) - 1, 15) available_height = self.height score_line_points = [ - [self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.score_scale),] + [self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.score_scale)] for i, val in enumerate(score_values) ] winrate_line_points = [ - [self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.winrate_scale),] + [self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.winrate_scale)] for i, val in enumerate(winrate_values) ] self.score_points = sum(score_line_points, []) @@ -158,144 +155,6 @@ class ScoreGraph(Graph): self.winrate_dot_pos = winrate_dot_point -def averagemod(data): - sorteddata = sorted(data) - lendata = len(data) - return sum(sorteddata[int(lendata * 0.2) : int(lendata * 0.8) + 1]) / ( - (int(lendata * 0.8) + 1) - int(lendata * 0.2) - ) # average without the best and worst 20% of ranks - - -def gauss(data): - return math.exp(-1 * (data) ** 2) - - -class RankGraph(Graph): - black_rank_points = ListProperty([]) - white_rank_points = ListProperty([]) - segment_length = NumericProperty(80) - RANK_CAP = 5 - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.calculate_trigger = Clock.create_trigger(lambda *args: self.rank_game(), 0.25) - self.rank_by_player = {} - - @staticmethod - def calculate_rank_for_player(segment_stats, num_intersec, player): - non_obvious_moves = [ - (nl, r, val) - for nl, r, val, pl in segment_stats - if nl is not None and val < (0.8 * (1 - (num_intersec - nl) / num_intersec * 0.5)) and pl == player - ] - if not non_obvious_moves: - return None - num_legal, rank, value = zip(*non_obvious_moves) - rank = [min(r, nl * 0.09) for r, nl in zip(rank, num_legal)] - averagemod_rank = averagemod(rank) - averagemod_len_legal = averagemod(num_legal) - norm_avemod_len_legal = averagemod_len_legal / num_intersec - if averagemod_rank > 0.1: - rank_kyu = ( - -0.97222 - * math.log(averagemod_rank) - / (0.24634 + averagemod_rank * gauss(3.3208 * (norm_avemod_len_legal))) - + 12.703 * (norm_avemod_len_legal) - + 11.198 * math.log(averagemod_rank) - + 12.28 * gauss(2.379 * (norm_avemod_len_legal)) - - 16.544 - ) - else: - rank_kyu = -4 - return min(RankGraph.RANK_CAP, 1 - rank_kyu) # dan rank - - @staticmethod - def calculate_ranks(segment_stats, num_intersec): - return {pl: RankGraph.calculate_rank_for_player(segment_stats, num_intersec, pl) for pl in "BW"} - - def rank_game(self): - try: - nodes = self.nodes - parent_policy_per_move = [node.parent.policy_ranking if node.parent else None for node in nodes] - num_legal_moves = [ - sum(pv >= 0 for pv, _ in policy_ranking) if policy_ranking else 0 - for policy_ranking in parent_policy_per_move - ] - policy_stats = [ - [ - (num_mv, rank, value, mv.player) - for rank, (value, mv) in enumerate(policy_ranking) - if mv == node.move - ][0] - if policy_ranking and node.move - else (None, None, None, None) - for node, policy_ranking, num_mv in zip(nodes, parent_policy_per_move, num_legal_moves) - ] - size = self.nodes[0].board_size - num_intersec = size[0] * size[1] - half_seg = self.segment_length // 2 - - ranks = {"B": [], "W": []} - dx = self.segment_length // 4 - for segment_mid in range(dx, len(nodes), dx): - bounds = (max(0, segment_mid - half_seg), min(segment_mid + half_seg, len(nodes))) - num_analyzed = sum(num_mv is not None for num_mv, _, _, _ in policy_stats[bounds[0] : bounds[1] + 1]) - if num_analyzed >= self.segment_length * 0.75: - for pl, rank in self.calculate_ranks(policy_stats[bounds[0] : bounds[1] + 1], num_intersec).items(): - ranks[pl].append((segment_mid, rank)) - self.rank_by_player = ranks - except Exception as e: - MDApp.get_running_app().gui.log(f"Exception while calculating rank: {e}", OUTPUT_ERROR) - self.redraw_trigger() - - def update_value(self, node): - super().update_value(node) - self.trigger_calculate() - - def trigger_calculate(self): - if self.opacity != 0: # recalc here on trigger and only if visible for speed - self.calculate_trigger() - - def update_graph(self, *args): - if self.rank_by_player: - xscale = self.width / max(len(self.nodes) - 1, 15) - available_height = self.height - - all_ranks = [rank for lst in self.rank_by_player.values() for seg, rank in lst if rank is not None] - if not all_ranks: - return - - min_rank = math.floor(min(all_ranks)) - max_rank = math.ceil(max(all_ranks)) - if max_rank == min_rank: - min_rank -= 1 - if (max_rank - min_rank) % 2 != 0: # make midpoint whole integer - if abs(max_rank - max(all_ranks)) < abs(min(all_ranks) - min_rank) and max_rank < self.RANK_CAP: - max_rank += 1 - else: - min_rank -= 1 - rank_range = max_rank - min_rank - - self.ids.mid_marker.text = rank_label((max_rank + min_rank) / 2) - self.ids.top_marker.text = rank_label(max_rank) + ("+" if max_rank == self.RANK_CAP else "") - self.ids.bottom_marker.text = rank_label(min_rank) - - graph_points = {} - for pl, rank_points in self.rank_by_player.items(): - graph_points[pl] = [ - [ - self.x + i * xscale, - self.y + available_height * (val - min_rank) / rank_range if val is not None else math.nan, - ] - for i, val in rank_points - ] - self.black_rank_points = sum(graph_points["B"], []) - self.white_rank_points = sum(graph_points["W"], []) - else: - self.black_rank_points = [] - self.white_rank_points = [] - - Builder.load_string( """ #:set GRAPH_CENTER_COLOR [0.5,0.5,0.5] @@ -387,39 +246,6 @@ Builder.load_string( color: WINRATE_MARKER_COLOR pos:root.pos[0]+1, root.pos[1] text: "{}%".format(50 - root.winrate_scale) - opacity: int(root.show_winrate) - -: - background_color: LIGHTER_BACKGROUND_COLOR - canvas: - Color: - rgba: WHITE - Line: - points: root.white_rank_points - width: dp(1.1) - Color: - rgba: BLACK - Line: - points: root.black_rank_points - width: dp(1.1) - # rank ticks - GraphMarkerLabel: - id: mid_marker - font_size: root.marker_font_size - color: YELLOW - pos: root.x + root.width - self.width-1, root.y + root.height*0.5 - self.height/2 + 2 - text: '?' + i18n._('strength:kyu') - GraphMarkerLabel: - id: top_marker - font_size: root.marker_font_size - color: YELLOW - pos: root.x + root.width - self.width-1, root.pos[1]+root.height - self.font_size - 1 - text: '?' + i18n._('strength:kyu') - GraphMarkerLabel: - id: bottom_marker - font_size: root.marker_font_size - color: YELLOW - pos: root.x + root.width - self.width-1, root.pos[1] - text: '?' + i18n._('strength:kyu') + opacity: int(root.show_winrate) """ ) diff --git a/katrain/gui/widgets/movetree.py b/katrain/gui/widgets/movetree.py index ecd53f1..a820779 100644 --- a/katrain/gui/widgets/movetree.py +++ b/katrain/gui/widgets/movetree.py @@ -12,20 +12,14 @@ from kivymd.app import MDApp from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text from katrain.gui.style import ( - BACKGROUND_COLOR, - DARKRED, GREEN, LIGHT_ORANGE, - LIGHTER_BACKGROUND_COLOR, LIGHTGREY, ORANGE, - OUTLINE_COLORS, RED, STONE_COLORS, STONE_TEXT_COLORS, - WHITE, YELLOW, - GREY, ) @@ -268,7 +262,7 @@ Builder.load_string( scroll_view_widget: root id: move_tree_canvas size_hint: None, None - + : canvas.before: Color: diff --git a/katrain/gui/widgets/selection_slider.py b/katrain/gui/widgets/selection_slider.py index 82bb261..1e88b5b 100644 --- a/katrain/gui/widgets/selection_slider.py +++ b/katrain/gui/widgets/selection_slider.py @@ -1,8 +1,6 @@ from kivy.lang import Builder from kivy.properties import BooleanProperty, ListProperty, NumericProperty from kivy.uix.widget import Widget -from kivymd.uix.label import MDLabel -from kivymd.uix.selectioncontrol import Thumb class SelectionSlider(Widget): @@ -122,7 +120,7 @@ KV = """ size: (max(dp(28), label.texture_size[0]+4) , dp(28)) pos: - (slider.px_pos - dp(9), slider.center_y - hint_box.height / 2 + dp(30)) + (slider.px_pos - dp(9), slider.center_y - hint_box.height / 2 + dp(30)) Label: id: label diff --git a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo index e2d7c20787c0e04140d6a1b8ead5fccb85a3c940..7d18cc5ace8c03bdeeab15bf3e9d072f73371548 100644 GIT binary patch delta 3677 zcmZYCdu+{j7{~E1s$H*o(F-jtHPp4VC`D}(GM#L!Yxl>7(r%=sHKk;mGhMT}WGfRI zR$<7QBnf$)CYd7>z+V1br|amEZ)__-yQs^RO$Hqd#s! z?Xv?z*x!A_g(eV!?G2@gykW@(`iR04_E3CEx+Fdj923M%m|YoCcaaRG7$ zx5)a-(4YO?2fDyY)Iy)22JS+g_<;4FM4kAY#n({dZX-Fm2dMc0WUmTDq56|h>!g{J zP~)@Eqk(x`@NuPlY2YekEmvvr7pN2MK~>-oYJmn+Ju|#D}PPf$XLe_CO^v0JUK{#^Q7&H@5(_ zUK#4-8%)oqT=b@)7PUYF>cqEDCA@IGs`Ps;K8jlKENa3H^DZi3KaQ*ML8udUM~dVUQHhO4&3gv5 zahA2`T3mpE`u#8ELMJLWH=!!=73v;;i+UK3p%$)3RpKJ*WKF0ITCBeV_0`6Ks08Cs z>kmM!mw`IiH1ud-9v50@F>1mJ)Pfae6>7t3)JgZD<{d&MbQbljG@|C+vi26#x^1ZO z0lbe@p;+vU!@6_-HDMGDdRixh2Ntlj-xD^FcsCGgNyMsR6>oYXXZNU z8Tb=bsaDgUmy6;kGto@;>T%<&VG3%&9E)d|1^6NDOR*CD61^wiiff6l;@4Q*$GKD3 z>q+OphpwlvjOXEz&4Bbpzi$f)d+?)FLq9VWRjQ{@3FIKJ z1h)i3@gwWsVb-B;K|N}n2Gj|!V=%T_f532Wf0)_R!-X;&Xr`kkW+D%;%R?oy8uc)4 zLv2uv+HjA>2hEeH16{EAn)w@QpNFXR0#m&6J-xV4M}O4DX{eJQqc&``_$GEFzJp5euK5VViG5PN2}C3P9ygc^-Sbq`g4yOAROyOQ58HB7BGuOa z1M(AgKcVh*EAnyiBfJ}Bq1JodEI}o-!d%%d_rJm#HliM)Ef$|J&zKib3tlmATl;qL{-S sqe|z_E6M-=faKV+u!yH0o7`_v`}Eq~gTno4V^fPeb(^b delta 3679 zcmYM%4{*VAHY&-?TL^ZtB)-(9a2E-egPjIY1S z@!whgwcy{i28x{97yZ8vQ`}G76o0@bcomcJZ)}W7F`>8(#uN9(Ryfq+0*oV`j}f>M z`2^fse8*C;3Dse@c?=s7pF>S}30ceC#UzYiP!zVr`q&Az!LF$O1F<=d!9?_9LtKJd zrvhVG-@Q*k1A}!H&K*Ua@JG~u8nYHP(LbmSBrr=DrlB(6MfLB6+IW`L4?~@J9I|&e z+1iV+A?v%jD&S(&L@Q7o-$9-DBWvG-I`LtPPonyrL-yoqP~-2RGSGlisJ$6#o(^Uv zs(%&+)Nv#QK5i;s>R5`*;TBt5i8@ggDg)b46C6Qh?ldOgHPm>mPSM4nHsC?kcR`JN z68X4i;sdA+oHj38`(LQ5j3G@Lmuz-H_T~nn z79N8-h%aCr=Acrv64h~?#X*ZdLk;{MHSibI32&n|62|VdU?QeqCuA?~Y1Dk{g8kMp$)?STT;7?>t7fGN6Qc>@LZm4+%o8wU9r<*0%jCdaE zAeG3^HsCf=&^u=f@^L%(QitQH9iKC6Pz&G1x)k$PQom%>2|J+bdz%AL2O5UT)Hu`z z^Q^tJuAci}KtZWrURUAVyQm2_qXv9xoZux3wK7< z_p&$(wXtlB)9-&g1)Z$GT!6|*CF-u%q8`d^sEKx?GIIzu(RZkYE?WCl)CO*$Hrjx^ zYyL#kd>v5-?2Q3+97;hGO+*cthMKU{T!dP%0(Ii`sBxQ78`_6@W{#l7owWLksCj=w z^{+)`DxCLnIHok`{xzUA6?$sDsD%cjc02~TZdZVs;8km1jk@~{R=?9cf;!n5Yp+4g zcMr8rLl&Xvl5i$=OCkTQDQu#mB_2n0tU>Mcj>XaZY3xJX91C$Y4#Y3<5sXO<9Uudh zp={LnvDgY{U^iTjJ@IqY0qzGVJW8Q4t9QWesDaO+?y3m&EG)#nxD@;0F?<^vG5h2A z0qQD#LS^6zYJmq9M|nc+t#CN?9W4&brl1rp#4@Zv4U8i#n$Ux4Ps0*?0=1#7sApvt z>h2GtGIzo}Z(cEPn_;|l)Gsb%z@<{qglX2$&FqWi)DOWo@htYkqPC zYjG(aY|o!=e1>~bzxJfJ3U}cO98a1j;qQ3*p@4HEI)+Zzu~X^STi4W z;+Ih;C^y$w`$miRqB8Oo@(XmQkO$vgLp{t5(m52SVm#|R9|cWZX1E5v-RcjZ zuH+k3#?D|AUbOhC#W&1(4L7M!CiElK29l7U zzRSQk%tp0OGH0Q#pd2-R6>7ulF&g(;`%!EE*1Uk)V2yb%KtTf=J;sxYZBYviLOp~N zQ48du7A%v^#x(Q1p=nOjf`?Lp0V3^l&m>Mx_#4cwuilg4!q4M;~`YOasPV^Asd zp*B*ET5yfU8?YYncGLnp&3!nU_z=cpN{`S+yr_Oz$khkj5DJ<&-<*v~;bPQ7w+gkP zgVufl`RTeE)SV|}I7iWCq86Hlns1)D6t!Tbxz?ABiwtKRD1I2B`v z+o2Zdj!m&YYJpLxUz0C*G&(apn3PZ$9y>j!)L)oeFr`-EejD9N9gU-(jP@mx{JtKdaV%Z2$lO diff --git a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po index 03e3ce5..2aae614 100644 --- a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.po @@ -762,3 +762,10 @@ msgstr "Expand/Collapse" msgid "analysis:playtoend" msgstr "Fast playout to game end" +#. TODO - hint on player name input +msgid "black player name hint" +msgstr "Black player's name" + +#. TODO - hint on player name input +msgid "white player name hint" +msgstr "White player's name" diff --git a/katrain/i18n/locales/de/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/de/LC_MESSAGES/katrain.mo index b86b0eb63ceddd7ee0b390b518cce066fab84796..972b258437b2a21c6934deb3d17705e7a1c4674e 100644 GIT binary patch delta 3676 zcmZYA3rv<(9LMnkLUK`rm%FIEVoIQbctHgfRwfIVtYns@7G5?GL`8+P<&(%Nb&gCO z(`W|jW=^{Bb|c$N^AcWWGqZ_QYx7R5QZjE*-{1S5Ew|Xq`#I-%&iS8n{^vZ;d&9Zy zI6t`pwi^B}@ZXRBu7^}J=49{xjHP&rdNf|b2)u`J*gMRaP#l7)k3<(v#YCKA>#H%G z`X=m&jmXC_d-?9eg%(tUR%;uEQ13tmyoH)mFpXm{7JFeD24FU7g1M;nGq5j~U=-G1 zFm6MQvlGJ@-+W9#9l!QoFy=gJg;!A>?pg!rr9fe*2@Jv>n1#x~Bvku+)Wi$z^%qbp zE=AU0mf8E&7|i%)qY7Au3e_@-Y|q(n@cjX6(;fNJgLrcB41NsCGH16&Bd* zbFF2l1y!OlRgIcpt@l3r|E|5U7nS$LY3RPn-5<0K-t%rI2kyae)JN?{HcvhX-&U?4w*YA_a=yqSi|OfeQ?C4PWEV*%Fo z=UG=B)joQFFH`9_koq_rhR>nmzmB7@#i5`*>9iOA!F1}Q5_zU^9x7#PP=~G#r(-?l zGOYL~n*_dMM1=d-p%$1-PT7^0j>wG$9D+TRs11exMYOh*Qdv_F1 z;P?0=HVo##qBDfw1H6ds*p$qdAFFzVpK^*DSWOi50+!oKeg06&)YI69PU@?N(}weB z%F=utZ=(jjL;l$X^Uw(2#0H~Mmx*NCOv4Z?N5(QMQJHE)9j<0noKvU;v>{KXxn{5X za{#m@eQ+w{n;{f9N2UTJuojh~2Gjses8{ScRN(9O{$Hq!^%&`UKZKwr;Nf?EdI2AV_YcfBewkBjO`PWM0X|1Oq85JM{HIaN|+e|rXZ+F=G7pN6< zpc{k6`L-Yh6(<7+Vm4|5voQcGP#Ld6#jAEGxG21Xdb~bF1wM%!U~>&)F><_bc zCSWAyp|MigxK^>;!sJ*(6 znz`RZ-+;lW6-J{{mxSJ@0TnO{c}JPYF@+b+LVJD7BwyxsU^MqVn1HR=M{lxA6g1;M zu?Gg__#UfXsEoK!1I42zmV^T^85L*>>afm5ZP9D^1a7zWi=LL=nSs$|Me|DCOUjB? zE~s#q7cE-gE-oow?&)+b4fHIIJLDfzRa~-s!T%eKNLUr)dZ2IeGH-9so{WfKPf+&t NfT(94=xFbne*q?)es}-? delta 3669 zcmYM$4NR3)9LMp4ya=dZfXJJA!AeoNKnWITYV##AbqdP}(@>e<3us)jJExD1)Ro#& z%4uafD+ikSLND4hF`Y*0oKBJQW!B6Lt(jT_((3!W_iVZA{hV{2bN=U?|2g;3R_Bi6 zT!{*L$MEL|{wDGFR)}iG9O&}D-6*d&$ z`ZDZ@>yVFQ-sL-zhB{P-{nqa=occvn!0X6drVV4UBZE3)PYlBTs0C)A`j5f{EW{Y} zU>LrRnx_UMnBROvK?Cc34aPL0cG!#>&|7&vZT$?Y-$i6irUf;=9hHF)cA@9- zs5pJC*{J>_&{4+%3Vh5gzSPl+#4syueFJJo+fW(Ug9>mAmANL2##^ZInw_GFKrO(9 zYEMUv8-jeyxG3_k!b|o+rL`IrxCRxV4*8gUd@1k=)B-P~7WO-;Uz@FmvKnP78kG?j zhT;HJzby1+Ae#JZq5>NDnAv>ktd^h#u0WmjI#j%Kqe|qp0x-yey+6& z529Ujve9(5-c&CdxytxDYvRQ;rI-+&*8AI{S}p`{&kUsGVJ~ z&s$LO+EMd_F$qNzi*qnDk^JXS*hE7nHlrpC=bu6rYm!kJ$;DC}gS&7qPQd9sc$uh< z>VE^3p$7n19pj;(fXh*5v>J708}S6z;$`$a zV$4jO^r$i4;+J>{m-gW+fL~ExvO;kxyNRKm!gd>}59-fRQ4io8exp7y&6rg<)Xi6b z!z2_m@k#Q}DVXn3m#r0*y08rY|74OeoceHNF7qrZQ&p%-wHy^^3u*&9kzb%WVB625 zj^rmCi*1<1{AMIKLn)e$ozR1tU@0nKoo)XDm8ow~?}J9v0?yd_kEl!dt8EW_%$TRC zM)DPL!IeVTlb=Nv>jb| z9CZXYP=Rh^GPa`@ko1KAXPb#ic{VEEaE!t!s0~&)6cl(Ba&b*9cE_`*owuL@{Eg8V z@}&Rl5>Q9e2X$vMP&*rp8kdK<8$}q0b5I$04YiOObfNPp1)cS2)TOwCWYPSKnlLNJ zpV~2~z{^mVa2=}uM(lvwY+t$wuULV9xpE{F^A~QZ-``h7a-Y zAQClUchpXMqf(fG3OE!M@EPPCW%4nV$gkS=txx$gxD&ha{4gfs1=IrXVpIWzz@h$E zZ7k~Nm4M2K3w>vdT3815#4J>x0@S6Qk2jq)T;_4P-EP;S@~U~$=2g5>Qn}dWgC51+l9}%M)|^{G{{g#8fc5|Y diff --git a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po index 1b83019..3500a71 100644 --- a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po @@ -814,3 +814,10 @@ msgstr "Expand/Collapse" msgid "analysis:playtoend" msgstr "Fast playout to game end" +#. TODO - hint on player name input +msgid "black player name hint" +msgstr "Black player's name" + +#. TODO - hint on player name input +msgid "white player name hint" +msgstr "White player's name" diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index b21422bafb28e696957b881452457134de5ee46c..53cce0643287bdc04afe64158ca22600c13ecec4 100644 GIT binary patch delta 3667 zcmZYAe~iy{9Ki9n!f}4w4|hi{?pu-{$qCox#2JdQQrzf|lFQwe-O=wu)K_TLmM}9@ zTDV$uqh%x)N$bav5L1mSl?}HwH6^tp>-oIzd#f$``aVAI&*%Mqy<1h(SR4woZ8bl54&PV9Eh!PIGW%nwEtA>jXvfXyig(55U!W^K8rwgi{eDJr49)2Hbh5VsdFbV>G}wXys007rcay&m<_9p(mQa zAoPAII_?hS6Yk5V{$4yBA1sNkLIc;L0qT)Y*vprJ8_@*MqFZqpO)!@%?4Ll}g=ob} z(8`R%b~pv?cW)Q!Z$?$zaKZ)1C#>YlJ$nNkxEYq*PY_6~enn-_i!r_>YlabuQ z95miybmgm~$=A8KmK$5q0N6O2XQ|9j9lk3<)v z<5xx3;Z?NXKo*h=A93OPdkFpQIf{HjBVVrcH#Flb_!ZJDbm9cIlo;(-imq@{y#GM7 z8eLEgTB*fog3DW;v;XVkgF3YI@5lCMXuu=rfK$;6Xu@eM*Zv*R6?R986ndeF4MWF` zK_@PY_se6u3Oo4z&*Q=sEsd^4EAbAx$M2zsu>lQy2(831bY)HG1n1-PR@B#tJD>?( zjmGbf#w$e^b~h&NSiyyXoE4=xzP{zV;}qjEmaTxBvRE-h^}NjPQx->ftzp=j_46WUtESg zaXVV6uaPd{1RD1u7Gf_tmEe>l7iRbp`ruU@fCrGOg=X~i$|*=4y1qDp_Ki3i=V1fx z#4)%ek=l|5v|@+R_$SfQpTp}h?Ha~nav&G(;hRW|umuft7%g!wKMwwt>y2(nKU{|+ z(L>sZmi8pN;$P9q{e@O6y;mxMJTzW!w0{xOFBwM12W4o$3iL2lp&e^*3ogMESacnK z+cBqi2%lpW?#96^>svgB+i)NC{so_AU-sf`_P4ZE2sif+;UMjr8~FKU{%{-huDF6= zXvR0N4_2ZWeH*5shourdJPXl^tw9zUHed#Rif-9aH1S{1gP}@PN`vqvc0XUKQ z!x%0Myc|8fb?5{iVgeh`Gth(vyo8oI?WWY3$VA(@n29~({X+Ec4aF?H8$AOvF@f_j zna0J-T)6U$n1%146YYuj_oFNO7McW#Xk{j#m8po% zM$ToZK@(nw{>|8gR%{Dq;f`eN@CABEjw8Pj;deAZ7RxlDVl?CN==)rTPB;@yyc!K$ zgSq$=dI(p==j+i#>d=HgK({z~lnYn(117K;U19z$smhcf=Pis!C!UY~l0A38W z9(2Obke4YO!8Z6cnph)t#gk|P&8hpzki*9H zH~Jc$LAE!fm!!@>DLQ^K8gB-ga5Y-Fh1kmX|Jjy{5S~L1%?s#?cA{^`9yGDNXvq$u zfse)eXV8FW(cg^=_#@^GPgUekw14YcQ(KcA?TZ~63fvEE78(bp%Xlc zCbj_WzX)B?D(r@}=oak4+i)Lx`ZGpst?N|OCbznLW>whk%Ok0$1n&#p{7IBU-1 sTffg9(k^fAgR>s5{Qt9z{1t{s%qF=yI;#>5BV9~@15)c^nh delta 3550 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 diff --git a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po index c7fdd84..25753eb 100644 --- a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po @@ -821,3 +821,10 @@ msgstr "Expand/Collapse" msgid "analysis:playtoend" msgstr "Fast playout to game end" +#. TODO - hint on player name input +msgid "black player name hint" +msgstr "Black player's name" + +#. TODO - hint on player name input +msgid "white player name hint" +msgstr "White player's name" diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo index bb8458d590f1d674b49703bbcb12d861e23d9786..c7eee52eb852ea7b15672e5605d13df65bd9ab13 100644 GIT binary patch delta 3679 zcmZYBeN5F=9LMo<6+%T2QLe}pxoQfcqKHC(f}p15Tx4jvm5EA;Aoz&c(@%*O+RUev zH2%N`oLaax@_}j@rZbPTgz0{St zPL#QvUqbyh8~!!$zZd^oo>0q}GeQ5^gUhqD!|*D0#rqhJLBYlZ;s8{8IELaRjKZ0= z{SJoE-hctP19>@SAMahbQH$zu(prz5Xx~5uyo<`IBc0vY13P0J`e7<6!7-@*(=Y<_ zusfDwN8E~D{Mv$Xtnw=N`Zn=3G~DEn1ZT68mj-ZsKm4F z{Z~*c&PUc@me}Vd*pd0oT3ui{D$sUR$7ZXh|DR@C@TWUmUi zQO^gW;yh)28r44=9d(?`1uwIlH+5W%#4_c!y$7|TgQyDBp#oe&Rqh&g!w0DGAq3^p z^hPBx40S&pHEuHUGB1Zxe_brJ58kzILIvK53Q&u@%=f%0a04pATd1vgh)OVwEY#nN zY7a$KECp4W3D^N&K=pg68}(O4`P|TiZz34BLYNA?Hzw@?z4VB10)?mt` z=TWFF9f=y3Zk>kYY8Ig8UFmS46|J`&cA!dCi|Tm7w(D)X88z@eYFr?*X@!xfL}F1B zrlJR@Ai0@BRJ;<@$~Rk`U0n3#Mhz;!CDe+qqe^%iRkDZnc>vKhK{#*ZV1}Y57>D}& zPe;XBWGz9B-(;=8p0ulwg*fI27yA63Lw)yLL|&$WH?8zfRL1T27Lr|26MM0(#HfDh zs1-hE@6WatpcYh&s#FOo!F6rV+5bxWU>~aVhiv;eD&PgwfUDNKsDuMpuKIUItuO*9 zlIe#^EEzR!ENbFxdq2mv^D$7L|JS+Dib}0pQI*(_+T#PL!*~J}_#CPdmr*NgMorLS zpS!59CJsa;*b5au78NfYwXo;WQOCJlD9|$0fK{k~>#P;13HPE_dKfjX4wcXa)LCgn zjk|8|x1i!aMD_2)_pvJEL4S;oVE;8Bi5oht<4_aLLS z94w3E>lJTeKkVPzcgmkZwdbH0-^XO!gIRdR;X*4(h~irb$KqftM`D{}sFF3I4&7h) zHa@^2e8bBamodNLGTL!`mbE3jP~-Qb;-5yXya5yOE|#D(g!DAvb5yCm#2t7NHL&1G z->=+TsEVw_RrnF=kh=T(N*jqf8?mUvnt=Y8YRy2MkqM}AQ;@Uam>FDXKrSl40@NWa zw(U~fNqa5MVx{ry$7{4VMpIJSt=JPi1Nmvik+J;ofqMrT6ODH$XCy|(F)^kNB@xUV z#t)Fo;nyhMn4EUTd^+5>lAw{kzg!|vrB6Y2$z&l_GexLMY(%!(>_(l9W2ln!9KJr(b3)?%l+nmJGvlmzsOKLd z$G~hu<}h`bhOMXslT&>YOhm<9hLf-yN8_)k%JmsV{Z)aOQNEAYaMXh&RK{t@xiV96 z2s+3)G}WlYe?)E3BUB~gh^|wfgnU9xCMw=+^us*+ybzV>3Wp2rO&RKNRbT`jLC&SA zN9|!}mZyGwQCpIT3Y>;IE8|h6o{l@2_}$*WXVrnw!~v)U_C^-sm}D+uxRK$z zVdi5v?Zv1SeSiaSD@NnDs9&*WjKWq_6ZD};OHf7!)vZ3 THg%|Rj~V3G{l&*d+Nb7UNtl3< delta 3671 zcmYM$4NTQl7{~F0yjp_Bn+OtDO+^LNCa91~YC0vP@@>QlQST5%sDP9i{vk?j>MB@? zPR*HSYUUl}zaFHTF-JoGwSH0(rmIAlGIk5F$$O?U-a%XDBg1~aG|K8^u61Qp;gRR2jBi@6wy z<=7S9L9J7dVXSYqQP4n-x51cGs2%=<8qj9FgPQ0eDu4)P@yEfa45Xm?r=tR&Xxnp8 zJI+I5H}mZC*RU(=n<^D>C2FGgQ5`p-cKn%r{sn5sCv5#Zs$Vk_lW9YZzmLj55WCRx zUZ{Bzt!b$K6VXw}85DS#Lf+J|5}CuSwDktmjy^$UU_WYtCRFAwVgz1Cjo0cFO&BTw z7pi?IYTOv)WwOJ`zY25ggEDI^YT|m-1Ur$JY2-~4pFsuqGb*r~sD2%`9zrzAR0Jv` zE)2mWRKHa8W*~z6YoQr5@G=W|(^)M?4P1db>pE1wowj}q6~IO7Rr~xN>L|lVlg7nZ zha$0=NvMT$Q5z|8Y=>p26xE?RZn1Tbtsh4Xynq_`8)}E`s6hOQP76k291cNZF_TgA z<)L<7Vy(iy)SWdHG{HX9j=w^s^eif6m+bRa)B?AWHBAT=EfA0T9vF_AXR0+1HNMzd zfxW0NM{T45`Pe$yJ>EazARKL#WJrjhg5O)Iu%x`88Ak zcTs@`k$24>iJET^YJ(Z*sN*yWnkXMNU=eDdrKw#+|qA zEvR|_K=r?a%2XiV%Yhgd%lT_S9~yLPQ&0;{MMa#89JeV!P4KpT{vqn@x7+rE)+W@> zF4^a8sQK=r*6GS36iqZP!r^h`Kas*F8pdD~>Q)EvQ#b%)P!o>Bx%dKZ$AdTz^Wu#e zg~zZT-a|HNdOz-~r=g4bi#QsW;d6KpwSgcf!I{+K^ zDkIae1`AP_^G{StZ=vo)C+d<0_4l1^m^Bi0H)2ua`lIed64Ku>qbO*COw{F@V(YW< zW9oBo4m%CtJPN712a;0i-(oMk$@!IG$Y5i#@QoqH48(6pXFT3YW?>8)N+1|Dj87c8 zh8t7R#o-(2N#9OdNBI6?xq(W3XexhPU_T^lW;`krZseFvCF*XhL#2EdDkCRR8NGmf z0?n_ej6OhJ=5Cxr7WPBkKT}FUmu59;!tI!Xji}UJMP=r1R0_>VU#f#qnd^>fkHIKR zKn0p=>r=1~^?cNs*PsGijgBJTKtX4+1344pL9%ELqdH#2nb?k6@L8_BGBXo(xymsU z-$e!bJw{^-7U5mwG)z7p0nNJx6;R`7&R+{(ra>vZg4`qHpYAge^*kFnev^yLWvX#3 z9zq3p54AvWhHv5#m_>aSj=`;{47H*%a1{gab_V&^gLWDeaVHMK$fx+;#<9r#GsURL z>rh8?6qSh^s3U4eKAFak)ihrp)B=g9=gFu*N1={pGU`s{ITT_kEJrS+S&uryGpLTg zppN7&YT{1R9SLCjN_9`vzEwduoPo> zP>l*?Jr2Mf$Vc6Lhx+wu#{>*{+Lyva~_6cQ8aH+aiy!g)Z50u vB-bm&?t(J6Ye_*-xho|l#kH)YVsZZB(%0Q(RW2{|D5!MLPw@n0CI|cn1v-IB diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po index d0f5097..3f332f6 100644 --- a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.po @@ -847,3 +847,11 @@ msgstr "Expand/Collapse" #. TODO - Menu option msgid "analysis:playtoend" msgstr "Fast playout to game end" + +#. TODO - hint on player name input +msgid "black player name hint" +msgstr "Black player's name" + +#. TODO - hint on player name input +msgid "white player name hint" +msgstr "White player's name" diff --git a/katrain/i18n/locales/jp/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/jp/LC_MESSAGES/katrain.mo index e9dafa41db37141bf63b16255ad1100e00f6308b..fd191bbe4d080fb4f2b78770b829731fa720df6c 100644 GIT binary patch delta 3679 zcmZYB3rv<(9LMp4K!hMF!YjfHVwjYfB6-E&^+M_*Gw(`fVY+l&yr#LfUM1SR%*=UV zs5LKCgOCA z!!nG-3e-GXFoyZvCloaBP*a0*=TR%HM-8}bhA~QkVo(XBVJK#yb|44U|4CHhqpkgU z)QSs{HMlu;y%Zyv-z`@G%Ta+gp*rqDt@v}h{w-?7XRQ7cs^2vvM|T@FzB$=z2YjgO z52NDrF$bgikH(-nPNBfZ&F4!UmmslRxz)F!RsMTnQ>(DQe|w%;38e9-yHL72qst#aB^VcmuU%ckFru(KSH=U*zDrp(e;hJ^$lT zab}sNsPU`J4cLx)C9;s9`+|a=-;=0!&l%+7YWdPi|3qcnjJJ?%jhZ+Wo3Tff)pU!ellpa#^Lw@?X3uw3V+7k=l>N7T2YxRh6=FWuJ1(M^UtjPn0XPk zvg>wTK^3nRYM%DUCD#QNcSsWZUrb>V4FNoEM)Rjo1D?Xia00TsZaJ#|dw2rllAW84 zKVv@}lfqjMSMsH&VmE4s4r3?$4*OsOK8js~?Y)&v#DO#vV=C@O1vrgbQ61_`{DlR0 z*DOfo^%}w-FU+U?W(RM=;XKnycmit6XQSdQ#>a6zD&gQc3d%4p&AV4As6d@jTl@xw z;u_T9slc!CeN;lTJ9_tifmw!%w*oa`1uB7^sCWlaJ6nVF3%X0z;TNyL-9>ebe9#Nj z4i8aJ!(Z_#F2XbH=d-MQY&wq?e*BPguVX}K&Jiwq#JP2Ns*BgJuq*#tP(RYmxeJV6 z*`3?X{H`d|xgVPGymF&;THE&W4r3bfsJj4aE615LQHOB}a$MXx)C%`l{Wxlc_1FR% zP~$^;dpqSvAN6$1V}6%IfknHer~x0E`;pu1j-k%NHPp`BMQwdcPLlMQ$*4p+T0INZ ze}Fl{t`{Ji<>q5h0X9-dz^%x^bYG$ZT|xzDzz!JR*IQXSYUMpJ6rVv|AB|ebJnWC_ zQD@+ywf~N*smEn`{kLba{~B20j7s=4hU)o0*HqvTVNWhxwhq2QUdLoqppIsD)QWQK z`qSnZ)CwnJW(aRaR3eqRUjKclI7dQ&qemB>(3!0~1Yau;10>b-Hes=7t5@c5#F7YkEo78NX*Iy<$bpm=KPwCN>ttFFh+ z3a^@xaIl$g{7o@gbAoPaW;n?-x=g%IOkI{Xq|9j+rq=hz^KZG=_jAs9&iSAJ`9IJ5zMNkZba_pX zcPX^-Cda=E{O`p7x+dy5cc|6>cA)t={YUW(w!<43fe-Kz3~%lCyJIN*!PpfiTR#We z(tj13;s)g9xnkbiFi?t`aKQW;ThOmT1-yprGeh_uyO6#9Q&8tCjau*7w=tEQm_MieBLsjl9hG89Qy>_SRTB8yO zpvGfS>xLpPHz}0*t1-_mL8h(O<0O5(FWAScdcJ;{UfM_r%?-kLY?p~Dv@Ba(}wLa3i~3txbdiX z$*7a(n9Hy`eQzxd1=x)`aRsWR-=Io%&aPiUZEy?O(>0@`4LYN~2jWn1CYZ^n^;u>C zM$%u7I>;8}W9zw(Y3Ms=7xHp@dDDa{RK_)CEo$R>Y$!3`N}3meI$OfOa zl}bh>m|@oo8^*c+MKo0U^$i2gZ9@gziCS>j{2uj1a|Jd3XVeLABSmrdQ3-@n4z25i z+PEKTJjwcFP>D^&w)*_frlFJNm_?|HY(d@Y64XPv2Nmc5sxn7WfvQm(U9#&pPzn5j zO0)@eSN!&A0D^VM6M4kA3)ViIhgbtyenPaGRCvE%^ zD()|+`FBv23gLS>1fx1~|FxhS1A1y>P#aA^Wjq79-7W_eV1-@ZjJo$bYBREMk7^p^H2*4@msu(i*a9P%80$X z@I!>Dyy;U>gsRNj*c0EwL3kYdVNh59K(QW;Q4Ea002ZMFY)74BKk8Yi!W67F2L|}1 z3vzBV&Sd*&V2PW&U-~9kPLH)WnO{ufwDC?_wPu ze4IZX@FVJ(%*lH{!Phpf=tb4=LT`T2a86(6it&SJf8MYde$wd|$NGQdq{i{(Mx5aT z`2A?)krg*u6{wB(AHuuHN7;oY_@(S)jz&F%vyjKcWus2G+WIA^6MlxR@HpyLoJD;) zZelpz!>6%bqH{gi-_53>1+SUwk=yLHp(=71Rr2r5Gv-B90#~hHkD9M1O}0f{4G?h>!D)1mw#~{duVPi%=V{Ma3^My?r#;!&RZaDqD>3PZEimI34)}xrL|z#i*0*LM5^n z8{rYucqJ;aDon;2RGh?-{zEqjH7_0cCiGl34V7{$D&P*(r=bj^u>y7Pe?=wGW0e1w zOQJaw2Qt14b-fG~=S#ENyo}no4)qY(tV zi%=(Af&+q_TZc-dVvIlk6e`YD)V$wqyvbPRO=BROMpNvKAsC0sG!gX-3`13DJnE}> zDk_orsDOFqYUD1ulJXO+5<<$u!*WB~WTh15=ceVPCgtU)qFLtos6e4J(v-`%-Tjhb-6+Js%{x1s{xLFMGf391j)ClN4$#oT+Rh8cG@?$}f?9Cb>cuJr3PdFki=LQ>sz4HI{zO#bIrjQ2 z)QJm`Gnf)PUW$I~Z&s^;n^1wuQ4{x~PW-hUKZ!bVgY92J&1*$+Gxg**7qPNP16^Z zKs@StGHTsq>ovzJ`3vI=*zzDo_jeqBg2V%{ycJS5b-Fw+2!kjYp$y z=}6SNWa~5}SF-@M?;B1UI?-A?VH>Jc)u@Sew%=s?EvSX}Q0x5JO(%>(B{CSb;aH5s zXOY~@LR7p`)X6tmojYjsCQ76o@ z*XLM^PzQP$RjE=`f@?a*x&K@3z#dfTt8D*URKT;S1y`(hPzn2TT+Q!>I$;D-Bom8D zYz%5$Dr(~#dp*zg3(;Ti|0^_fqB84dR3$z`-Q$C(hp`S7xE@uBM%2k#P#d({aS!UN zjr~yx_CduTjEa|xI#@P3H8G!t0xd%=coP+HjdcrZ!`-Npeu-Ll6qV3f)U(ozT6fJ} zZ%4)LK+W&U@3ATriQYIYg8Q!p30%0(nl&KGZ$0Lshg9$KXx;0G$J4-3tz)GOfYy@e=9;pFisU zD|ZBy=r?!_e?~o|+a7aQW;g2DID{&7t-XE*_4{xMRngn_x+i5~p3{WTP~aF;=HpNg zQwFN!*|;C);GY;WfZuQIHjv*2oQ*M5VCo=#?Qj|Q>u;_ff83bo=pP&6o);cRb?EyK zHRd|w+40;?_BTnxj5*9e11i%E+=m$a6p3w4pi0<=x`$pP+@9ma#SfRt%uNu{&Cx{ zxBUyK3SPF}#t`~GqudX5Bs#S)gN7zfMrE3d+F&{ILYTKP6w6Wbt5B6WjGlN6m0&A| z;R8&;umpFU>FA(efKzcLDsEE(^;gO6*b9+7`g%GOP?;8^O1=_#bIcCZ4@xaQf%TY# z_c0U4u~>!*3C#xW-BV8M(nJV9dAWds?ABGHx0jW?q?tt^@Ed+Jiul#>KAPbs>J(H z0c%kk{(!ykC)6`@3-$KgMcq>Gr`+RVsMk3TqcI6}aAz)!2pWaRt7%puIhjgSsaud( zrXBS(52M~wFcr1Ihp2=qPyt=mBd7#VqY`UC9pobF*8c7ucN(8$_dO3lEyzSocm@@C zE>e9{j89`FYU7(Y0UsbgW@bW)F(a@DwNW{$5(lg`r~{lt#cf7Uz5l;;HVB9_7-&N! zlErRvnsp{BU_L6qBHLeK`>Rlu{0Q4|za8H>-aUUmszNoWTX_n*=hOIwhBCf|dPqD| z-G3f^Q3(WK7Ysp_G77cP08}F5QP02>RORO35?q1W=$5NGV3c=gQQq7_$Ks;AR|}Rn z7UnG|aLk*(aH;D?P_egbQTVY(!j{jQzqH{06XGM|BZ9|2w0J;C=W^Gqkx728>q$Z0 LA=4jPX-Cb!qXLd* delta 3672 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 delta 3676 zcmYM#2~bs49LMoLDu||FU`8PNpfm(UvC_gUOhB^)MY9|$AtNN=QS!*h^k!sfnk7^& zt!7$`I>|h(Y-}OTvYe^RB%{o1G07IEWi)O1{XQL343@BY7MQ+%EJS@4nIQ;XmkFKn&=-?0P)Py5z|o_$VBzeMg^Yh+6z%T zo`%G3Gu-pp*oF0No(lK?YNF++j!&U>ywN>>4YlK)uKqEqUn>%mwV}rUg~~t_yU_D< zQ1hfYhoSoCqNk3NDe$o}zSOZ6nZq7%^_8d{tw&{`2{pkkROa?$JRU=h*Xk541{FX6 z)jk+CZY1)t@p0r|g<|)h+F6I1xB)dmBl59V`O?H6paT3771+xr_{Vu}x48)UvEi{=1K6Wc#I;;7pf%l`%x*pZ9(beBX1+d?F#63TOI?5Q*q;Uz( z!ANYDk6L&tY9r;I>o6CUqIy)vXI(w)>dmNu`%nYFMeXoUR3IIRP7C(LB+Ni!u`#Im zrlEEobk4(6>fTZcn&2hWj^9G1bPpn3M{Q&!^4fa#A_e{CY(hS^g)epZ02OhovkkTINo-Fsze?(tfZAais(pkr54E8} zRHmk(0-Wid*S5EF{&f_T`bXLu%$`O~xB)fb4d;ibADTm`{@{So{I`>BKFYxe**>WEa8i$H_DstQwL`|^JJ%1c^_Ul~xR_89% z&RX2_Hq?B7q1NfbA{4C`mSI*B`7flfiiR9Kie$~w`BQiyjz&d%CsyJzJdLL@geQ~D zuEby;e*>?gGPDnK@k<oWf%4!ziWJ zL;ZDo7&EZ}JFwu}7)AY^^Zk_WLGAbeD%FRPq}Xw1Y?`0)LC6bYV^K$2jP&!Yh64A( z8eE4>uKo^&Y5xjGvv9)zvq!17u)QGliVU+k*gDYc37kZfWAGQ!_YDruGMkM_7m$Gt z93AI5i~8naYz%u}%tkwL{((#U$cAuGLs?)f4#K%eUu#6NYlo0yvrd=!XMP?Mn*}i& zSD-H0UgR3tSE##m3bnzWm;0AF6Lr*iIM}1GoC4XhX4GXnit6w$DrHyY_&>EXP^q7T zT4+A%tytpfPonxaBByE1sQHfIX#5-Xc8nV3_nV9!S+NQVeQ}L@(2PTiup)WpEFcU;>lsa^8i?z+%)Te{!tnpY28( za%lJnFU2!?sVQ0kvWBfd?vowFi?GKyKNI<=BPc{-v|`j*uXoSiLM^x(m8ma~H_%R? z=1KMllM8H$5S{QyG$^<21lVXu>xlsQU8EeJ05nQ%O z{zkS>_5W=KiQFsF5 zFnfyGEjT{ByZf-naIg5P$k>XK+E7(#@aF95P)Vq!I$W2qvqSjCq{M#Vr8$dY3MTNp zJXjV8%`6R+l~k4nZm%hyF{`3B5UOf#W8}cVZ55>@)un+sCFP+&W@ct!Zm_0udS%re ZrPcES?a-s7w)E!A2Cpa~oKZNp^M6nNqiz5I diff --git a/katrain/i18n/locales/ru/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ru/LC_MESSAGES/katrain.po index 41d000d..e08b66c 100644 --- a/katrain/i18n/locales/ru/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/ru/LC_MESSAGES/katrain.po @@ -811,3 +811,10 @@ msgstr "Expand/Collapse" msgid "analysis:playtoend" msgstr "Fast playout to game end" +#. TODO - hint on player name input +msgid "black player name hint" +msgstr "Black player's name" + +#. TODO - hint on player name input +msgid "white player name hint" +msgstr "White player's name" diff --git a/katrain/popups.kv b/katrain/popups.kv index b432345..25c6b6b 100644 --- a/katrain/popups.kv +++ b/katrain/popups.kv @@ -393,11 +393,13 @@ LabelledTextInput: text: '' id: black_player_name + hint_text: i18n._("black player name hint") size_hint: 0.75, None AnchorLayout: LabelledTextInput: text: '' id: white_player_name + hint_text: i18n._("white player name hint") size_hint: 0.75, None DescriptionLabel: text: i18n._("board size") diff --git a/setup.py b/setup.py index b192bbf..7af79c4 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import find_packages, setup package_data = {"": ["*.json", "*.kv", "*.wav"], "katrain": [], "tests": []} packages = find_packages(exclude=["tests"]) -version = re.search('^VERSION\s*=\s*"(.*)"', open("katrain/core/constants.py").read(), re.M).group(1) +version = re.search(r'^VERSION\s*=\s*"(.*)"', open("katrain/core/constants.py").read(), re.M).group(1) def include_data_files(directory): diff --git a/tests/test_board.py b/tests/test_board.py index 15a8361..7014a08 100644 --- a/tests/test_board.py +++ b/tests/test_board.py @@ -1,6 +1,6 @@ import pytest -from katrain.core.base_katrain import OUTPUT_INFO, KaTrainBase +from katrain.core.base_katrain import KaTrainBase from katrain.core.game import Game, IllegalMoveException, Move from katrain.core.game_node import GameNode diff --git a/tests/test_parser.py b/tests/test_parser.py index 5dd3d2c..83f0cc6 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1,8 +1,7 @@ import os -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from katrain.core.base_katrain import KaTrainBase -from katrain.core.engine import KataGoEngine from katrain.core.game import Game, KaTrainSGF from katrain.core.sgf_parser import SGF, SGFNode @@ -107,7 +106,7 @@ def test_old_server_style(): def test_ogs(): file = os.path.join(os.path.dirname(__file__), "data/ogs.sgf") - tree = SGF.parse_file(file) + SGF.parse_file(file) def test_gibo():