This commit is contained in:
Sander Land committed 2020-05-25 19:56:24 +02:00
1 parent 40ae451bef
commit 74c57f9433
7 files changed
+88 -48

No files matched your search

+9 -9
View File
@@ -1,4 +1,8 @@
from kivy.config import Config # isort:skip
ICON = "img/icon.png" # isort:skip # set icon
Config.set("kivy", "window_icon", ICON) # isort:skip # set icon
Config.set("input", "mouse", "mouse,multitouch_on_demand") # isort:skip # no red dots on right click
import os
import signal
import sys
@@ -24,22 +28,18 @@ from katrain.core.common import (
OUTPUT_EXTRA_DEBUG,
OUTPUT_INFO,
OUTPUT_KATAGO_STDERR,
Lang,
find_package_resource,
find_package_resource,i18n
)
from katrain.core.engine import KataGoEngine
from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
from katrain.core.sgf_parser import Move, ParseError
from katrain.gui.badukpan import AnalysisControls, BadukPanControls, BadukPanWidget
from katrain.gui.controlspanel import ControlsPanel, RightButtonControls
from katrain.gui.controlspanel import ControlsPanel
from katrain.gui.graph import ScoreGraph
from katrain.gui.kivyutils import *
from katrain.gui.popups import ConfigPopup, LoadSGFPopup, NewGamePopup
from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL
ICON = "img/icon.png"
Config.set("kivy", "window_icon", ICON) # isort:skip # set icon
Config.set("input", "mouse", "mouse,multitouch_on_demand") # isort:skip # no red dots on right click
__version__ = "1.1.0"
@@ -229,7 +229,7 @@ class KaTrainGui(Screen):
try:
move_tree = KaTrainSGF.parse_file(files[0])
except ParseError as e:
self.log(f"Failed to load SGF. Parse Error: {e}", OUTPUT_ERROR)
self.log(i18n._("Failed to load SGF").format(error=e), OUTPUT_ERROR)
return
self._do_new_game(move_tree=move_tree, analyze_fast=popup_contents.fast.active)
if not popup_contents.rewind.active:
@@ -276,7 +276,7 @@ class KaTrainGui(Screen):
try:
move_tree = KaTrainSGF.parse(clipboard)
except Exception as e:
self.controls.set_status(f"Failed to imported game from clipboard: {e}\nClipboard contents: {clipboard[:50]}...")
self.controls.set_status(i18n._("Failed to import from clipboard").format(error=e,contents=clipboard[:50]))
return
move_tree.nodes_in_tree[-1].analyze(self.engine, analyze_fast=False) # speed up result for looking at end of game
self._do_new_game(move_tree=move_tree, analyze_fast=True)
@@ -332,7 +332,7 @@ class KaTrainGui(Screen):
self("output-sgf")
elif keycode[1] == "c" and "ctrl" in modifiers:
Clipboard.copy(self.game.root.sgf())
self.controls.set_status("Copied SGF to clipboard.")
self.controls.set_status(i18n._("Copied SGF to clipboard."))
elif keycode[1] == "v" and "ctrl" in modifiers:
self.load_sgf_from_clipboard()
return True
+2 -7
View File
@@ -1,10 +1,10 @@
import os
import sys
from typing import Any, List, Tuple
from kivy.lang import Observable
import gettext
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.core.text import Label as CoreLabel
try:
import importlib.resources as pkg_resources
@@ -44,7 +44,7 @@ def find_package_resource(path):
with pkg_resources.path(".".join(parts[:-1]), parts[-1]) as path_obj:
return str(path_obj) # this will clean up if egg etc, but these don't work anyway
except (ModuleNotFoundError, FileNotFoundError) as e:
print(f"File {path} not found, installation possibly broken")
print(f"File {path} not found, installation possibly broken",file=sys.stderr)
return f"FILENOTFOUND::{path}"
else:
return path # absolute path
@@ -101,10 +101,5 @@ i18n = Lang(LANGUAGE)
class I18NLabel(Label):
pass
class I18NCoreLabel(CoreLabel):
pass
class I18NTextInput(TextInput):
pass
+6 -11
View File
@@ -6,7 +6,7 @@ import threading
import time
from typing import Callable, Optional
from katrain.core.common import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR, find_package_resource
from katrain.core.common import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR, find_package_resource, i18n
from katrain.core.game_node import GameNode
@@ -56,16 +56,11 @@ class KataGoEngine:
self.katrain.log(f"Starting KataGo with {self.command}", OUTPUT_DEBUG)
self.katago_process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (FileNotFoundError, PermissionError, OSError) as e:
if self.config["katago"].strip():
self.katrain.log(
f"Starting kata with command '{self.command}' failed with error {e}. If on MacOS, see the manual on how to use brew to install katago first, and add it to your path or 'engine/katago' setting.",
OUTPUT_ERROR,
if not self.config["katago"].strip():
self.katrain.log( i18n._("Starting default Kata failed").format(command=self.comment,error=e), OUTPUT_ERROR,
)
else:
self.katrain.log(
f"Starting kata with command '{self.command}' failed with error {e}. Please make sure the 'katago' value under 'engine' in settings points to the correct KataGo executable.",
OUTPUT_ERROR,
)
self.katrain.log( i18n._("Starting Kata failed").format(command=self.comment,error=e) , OUTPUT_ERROR, )
self.analysis_thread = threading.Thread(target=self._analysis_read_thread, daemon=True).start()
self.stderr_thread = threading.Thread(target=self._read_stderr_thread, daemon=True).start()
@@ -108,7 +103,7 @@ class KataGoEngine:
try:
line = self.katago_process.stdout.readline()
except OSError as e:
raise EngineDiedException(f"Engine died unexpectedly without sending output, possibly due to out of memory: {e}")
raise EngineDiedException(i18n("Engine died unexpectedly").format(error=e))
if b"Uncaught exception" in line:
self.katrain.log(f"KataGo Engine Failed: {line.decode()}", OUTPUT_ERROR)
return
@@ -152,7 +147,7 @@ class KataGoEngine:
self.katago_process.stdin.write((json.dumps(query) + "\n").encode())
self.katago_process.stdin.flush()
except OSError as e:
self.katrain.log(f"Engine died unexpectedly, possibly due to out of memory: {e}", OUTPUT_ERROR)
self.katrain.log(i18n._("Engine died unexpectedly").format(error=e), OUTPUT_ERROR)
return # do not raise, since there's nothing to catch it
def request_analysis(
+12 -12
View File
@@ -2,7 +2,7 @@ import copy
import random
from typing import Dict, List, Optional, Tuple
from katrain.core.common import evaluation_class, var_to_grid
from katrain.core.common import evaluation_class, var_to_grid, i18n
from katrain.core.sgf_parser import Move, SGFNode
@@ -41,7 +41,7 @@ class GameNode(SGFNode):
properties["C"] = ["\n".join(properties.get("C", "")) + comment]
if self.is_root:
properties["C"] = [
"Moves marked 'X' indicate the top move according to KataGo, those with a square are moves that lose less than 0.5 points.\n"
i18n._("SGF start message") + "\n"
+ "\n".join(properties.get("C", ""))
+ "\nSGF with review generated by KaTrain."
]
@@ -137,29 +137,29 @@ class GameNode(SGFNode):
if previous_top_move["move"] != single_move.gtp():
points_lost = self.points_lost
if sgf and points_lost > 0.5:
text += f"Estimated point loss: {points_lost:.1f}\n"
text += f"Predicted top move was {previous_top_move['move']} ({self.format_score(previous_top_move['scoreLead'])}).\n"
text += i18n._("Info:point loss").format(points=points_lost) + "\n"
text += i18n._("Info:top move").format(top_move=previous_top_move['move'],score=self.format_score(previous_top_move['scoreLead'])) +".\n"
else:
text += f"Move was predicted best move.\n"
text += i18n._("Info:best move")+"\n"
if previous_top_move.get("pv") and (sgf or hints):
text += f"PV: {self.make_pv(single_move.player,previous_top_move['pv'],interactive)}\n"
text += i18n._("Info:PV") + ": " + self.make_pv(single_move.player,previous_top_move['pv'],interactive) + "\n"
if sgf or hints or teach:
policy_ranking = self.parent.policy_ranking
currmove_policy_with_ix = [(ix + 1, p) for (p, m), ix in zip(policy_ranking, range(len(policy_ranking))) if m == single_move]
if currmove_policy_with_ix:
text += f"Move was #{currmove_policy_with_ix[0][0]} according to policy ({currmove_policy_with_ix[0][1]:.2%}).\n"
text += i18n._("Info:policy rank").format(rank=currmove_policy_with_ix[0][0],probability=currmove_policy_with_ix[0][1]) + "\n"
if not currmove_policy_with_ix or currmove_policy_with_ix[0] != 1 and (sgf or hints):
text += f"Top policy move was {policy_ranking[0][1].gtp()} ({policy_ranking[0][0]:.1%}).\n"
text += i18n._("Info:policy best").format(move=policy_ranking[0][1].gtp(),probability=policy_ranking[0][0]) +".\n"
if self.auto_undo and sgf:
text += "Move was automatically undone in teaching mode.\n"
text += i18n._("Info:teaching undo") + "\n"
top_pv = self.analysis_ready and self.candidate_moves[0].get("pv")
if top_pv:
text += f"Predicted follow-up: {self.next_player}{' '.join(top_pv)}\n"
text += i18n._("Info:undo predicted PV").format(pv=f"{self.next_player}{' '.join(top_pv)}") + "\n"
if self.ai_thoughts and (sgf or hints):
text += f"\nAI thought process: {self.ai_thoughts}"
text += "\n" + i18n._("Info:AI thoughts").format(thoughts=self.ai_thoughts)
else:
text = "No analysis available" if sgf else "Analyzing move..."
text = i18n._("No analysis available") if sgf else i18n._("Analyzing move...")
return text
@property
-3
View File
@@ -11,9 +11,6 @@ from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup
from katrain.gui.ai_settings import ConfigAIPopupContents
class RightButtonControls(MDBoxLayout):
button_size = ListProperty([100, 33])
class ControlsPanel(BoxLayout):
katrain = ObjectProperty(None)
+59 -3
View File
@@ -13,9 +13,7 @@ msgstr "Roboto"
msgid "Hello World"
msgstr "Hello World"
msgid "KataGo"
msgstr "KataGo"
#.
msgid "English"
msgstr "English"
@@ -33,6 +31,7 @@ msgstr ""
"[space]\n"
"Pass"
#. tabs and labels on the right panel
msgid "tab:score"
msgstr "Score"
@@ -57,6 +56,7 @@ msgstr "Move Stats"
msgid "closedlabel:info&notes"
msgstr "Move Info & Notes"
#. on the board after pass
msgid "board-pass"
msgstr "pass"
@@ -64,3 +64,59 @@ msgid "board-game-end"
msgstr ""
"game\n"
"end"
#. SGF and move comment messages
msgid "SGF start message"
msgstr "Moves marked 'X' indicate the top move according to KataGo, those with a square are moves that lose less than 0.5 points.
msgid "Info:point loss"
msgstr "Estimated point loss: {points_lost:.1f}"
msgid "Info:top move"
msgid "Predicted top move was {top_move} ({score})."
msgid "Info:best move"
msgstr "Move was predicted best move.
msgid "Info:PV"
msgstr "PV"
msgid "Info:policy rank"
msgstr "Move was #{rank} according to policy ({probability:.2%})."
msgid "Info:policy best"
msgstr "Top policy move was {move} ({policy_ranking[0][0]:.1%})."
msgid "Info:teaching undo"
msgstr "Move was automatically undone in teaching mode."
msgid "Info:undo predicted PV"
msgstr "Predicted follow-up: {pv}"
msgid "Info:AI thoughts"
msgstr "AI thought process: {thoughts}"
msgid "No analysis available"
msgstr "No analysis available"
msgid "Analyzing move..."
msgstr "Analyzing move..."
#.misc errors and info messages
msgid "Copied SGF to clipboard."
msgstr "Copied SGF to clipboard."
msgid "Failed to import from clipboard"
msgstr "Failed to import game from clipboard: {error}\nClipboard contents: {contents}..."
msgid "Failed to load SGF"
msgstr "Failed to load SGF. Parse Error: {error}"
msgid "Starting default Kata failed"
msgstr "Starting KataGo with command '{command}' failed with error {error}. If on MacOS, see the manual on how to use brew to install katago first, and add it to your path or 'engine/katago' setting."
msgid "Starting Kata failed"
msgstr "Starting kata with command '{command}' failed with error {error}. Please make sure the 'katago' value under 'engine' in settings points to the correct KataGo executable."
msgid "Engine died unexpectedly"
msgstr "Engine died unexpectedly without sending output, possibly due to out of memory: {e}"
@@ -30,9 +30,6 @@ msgstr ""
"[스페이스 바]\n"
"페스"
msgid "KataGo"
msgstr "카타고"
#. TODO
msgid "tab:winrate"
msgstr "Win Rate"