This commit is contained in:
Sander Land committed 2020-12-01 23:09:02 +01:00
1 parent 957cdceea2
commit 93841e9b35
23 files changed
+196 -43

No files matched your search

+2 -3
View File
@@ -4,7 +4,7 @@
[![License:MIT](https://img.shields.io/pypi/l/katrain)](https://en.wikipedia.org/wiki/MIT_License)
[![GitHub Downloads](https://img.shields.io/github/downloads/sanderland/katrain/total?color=%23336699&label=github%20downloads)](https://github.com/sanderland/katrain/releases)
[![PyPI Downloads](https://pepy.tech/badge/katrain)](https://pepy.tech/project/katrain)
[![Github sponsors](https://img.shields.io/static/v1?label=sponsor&message=7&logo=GitHub&color=dcb424&link=https://github.com/sponsors/sanderland/)](https://github.com/sponsors/sanderland)
[![Github sponsors](https://img.shields.io/static/v1?label=sponsor&message=6&logo=GitHub&color=dcb424&link=https://github.com/sponsors/sanderland/)](https://github.com/sponsors/sanderland)
[![Discord](https://img.shields.io/discord/417022162348802048?logo=discord)](https://discord.com/channels/417022162348802048/629446365688365067)
<table>
@@ -27,9 +27,8 @@
<a href="https://github.com/sanderland/katrain/blob/master/README.md"><img alt="English" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-uk.png" width=50></a>
<a href="https://translate.google.com/translate?sl=en&tl=de&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="German" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-de.png" width=50></a>
<a href="https://translate.google.com/translate?sl=en&tl=fr&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="French" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-fr.png" width=50></a>
<a href="https://translate.google.com/translate?sl=en&tl=es&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="Spanish" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-es.png" width=50></a>
<br/>
<a href="https://translate.google.com/translate?sl=en&tl=ru&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="Russian" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-ru.png" width=50></a>
<br/>
<a href="https://translate.google.com/translate?sl=en&tl=zh-CN&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="Chinese" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-cn.png" width=50></a>
<a href="https://translate.google.com/translate?sl=en&tl=ko&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="Korean" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-ko.png" width=50></a>
<a href="https://translate.google.com/translate?sl=en&tl=ja&u=https%3A%2F%2Fgithub.com%2Fsanderland%2Fkatrain%2Fblob%2Fmaster%2FREADME.md"><img alt="Japanese" src="https://github.com/sanderland/katrain/blob/master/katrain/img/flags/flag-jp.png" width=50></a>
+39 -11
View File
@@ -66,7 +66,7 @@ from katrain.core.constants import (
PLAYING_NORMAL,
PLAYER_HUMAN,
)
from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup, I18NPopup
from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup, I18NPopup, SaveSGFPopup
from katrain.core.base_katrain import KaTrainBase
from katrain.core.engine import KataGoEngine
from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
@@ -227,6 +227,7 @@ class KaTrainGui(Screen, KaTrainBase):
def set_note(self, note):
self.game.current_node.note = note
# The message loop is here to make sure moves happen in the right order, and slow operations don't hang the GUI
def _message_loop_thread(self):
while True:
game, msg, args, kwargs = self.message_queue.get()
@@ -253,16 +254,14 @@ class KaTrainGui(Screen, KaTrainBase):
else: # game related actions
self.message_queue.put([self.game.game_id, message, args, kwargs])
def _do_new_game(self, move_tree=None, analyze_fast=False, loaded_from_file=None):
def _do_new_game(self, move_tree=None, analyze_fast=False, sgf_filename=None):
self.idle_analysis = False
mode = self.play_analyze_mode
if (move_tree is not None and mode == MODE_PLAY) or (move_tree is None and mode == MODE_ANALYZE):
self.play_mode.switch_ui_mode() # for new game, go to play, for loaded, analyze
self.board_gui.animating_pv = None
self.engine.on_new_game() # clear queries
self.game = Game(
self, self.engine, move_tree=move_tree, analyze_fast=analyze_fast, loaded_from_file=loaded_from_file
)
self.game = Game(self, self.engine, move_tree=move_tree, analyze_fast=analyze_fast, sgf_filename=sgf_filename)
if move_tree:
for bw, player_info in self.players_info.items():
player_info.player_type = PLAYER_HUMAN
@@ -371,7 +370,7 @@ class KaTrainGui(Screen, KaTrainBase):
except ParseError as e:
self.log(i18n._("Failed to load SGF").format(error=e), OUTPUT_ERROR)
return
self._do_new_game(move_tree=move_tree, analyze_fast=fast, loaded_from_file=file)
self._do_new_game(move_tree=move_tree, analyze_fast=fast, sgf_filename=file)
if not rewind:
self.game.redo(999)
@@ -387,9 +386,8 @@ class KaTrainGui(Screen, KaTrainBase):
filename = popup_contents.filesel.filename
self.fileselect_popup.dismiss()
path, file = os.path.split(filename)
settings_path = self.config("general/sgf_load")
if path != settings_path:
self.log(f"Updating sgf load path default to {path}", OUTPUT_INFO)
if path != self.config("general/sgf_load"):
self.log(f"Updating sgf load path default to {path}", OUTPUT_DEBUG)
self._config["general"]["sgf_load"] = path
self.save_config("general")
self.load_sgf_file(filename, popup_contents.fast.active, popup_contents.rewind.active)
@@ -399,11 +397,39 @@ class KaTrainGui(Screen, KaTrainBase):
self.fileselect_popup.open()
self.fileselect_popup.content.filesel.ids.list_view._trigger_update()
def _do_output_sgf(self):
def _do_save_game(self, filename=None):
filename = filename or self.game.sgf_filename
if not filename:
return self("save-game-as")
msg = self.game.write_sgf(self.config("general/sgf_save"))
self.log(msg, OUTPUT_INFO)
self.controls.set_status(msg, STATUS_INFO)
def _do_save_game_as_popup(self):
popup_contents = SaveSGFPopup()
save_game_popup = I18NPopup(
title_key="save sgf title", size=[dp(1200), dp(800)], content=popup_contents
).__self__
def readfile(*_args):
filename = popup_contents.filesel.filename
if not filename.lower().endswith('.sgf'):
filename += '.sgf'
save_game_popup.dismiss()
path, file = os.path.split(filename)
if path != self.config("general/sgf_save"):
self.log(f"Updating sgf save path default to {path}", OUTPUT_DEBUG)
self._config["general"]["sgf_save"] = path
self.save_config("general")
self._do_save_game(filename)
popup_contents.filesel.on_success = readfile
popup_contents.filesel.on_submit = readfile
save_game_popup.open()
popup_contents.filesel.ids.file_text = self.game.generate_filename() # TODO: ???
popup_contents.filesel.path = os.path.abspath(os.path.expanduser(self.config("general/sgf_save", ".")))
# save_game_popup.content.filesel.ids.list_view._trigger_update()
def load_sgf_from_clipboard(self):
clipboard = Clipboard.paste()
if not clipboard:
@@ -513,7 +539,9 @@ class KaTrainGui(Screen, KaTrainBase):
elif keycode[1] == "l" and ctrl_pressed:
self("analyze-sgf-popup")
elif keycode[1] == "s" and ctrl_pressed:
self("output-sgf")
self("save-game")
elif keycode[1] == "d" and ctrl_pressed:
self("save-game-as-popup")
elif keycode[1] == "c" and ctrl_pressed:
Clipboard.copy(self.game.root.sgf())
self.controls.set_status(i18n._("Copied SGF to clipboard."), STATUS_INFO)
+10 -18
View File
@@ -47,7 +47,7 @@ class Game:
move_tree: GameNode = None,
analyze_fast=False,
game_properties: Optional[Dict] = None,
loaded_from_file=None,
sgf_filename=None,
):
self.katrain = katrain
self._lock = threading.Lock()
@@ -55,7 +55,7 @@ class Game:
engine = {"B": engine, "W": engine}
self.engines = engine
self.game_id = datetime.strftime(datetime.now(), "%Y-%m-%d %H %M %S")
self.loaded_from_file = loaded_from_file
self.sgf_filename = sgf_filename
if move_tree:
self.root = move_tree
@@ -295,14 +295,18 @@ class Game:
+ f"\ncaptures: {self.prisoner_count}"
)
def generate_filename(self):
player_names = {bw: re.sub(r"['<>:\"/\\|?*]", "", self.root.get_property("P" + bw, bw)) for bw in "BW"}
base_game_name = f"katrain_{player_names['B']} vs {player_names['W']}"
return f"{base_game_name} {self.game_id}"
def write_sgf(
self, path: str, trainer_config: Optional[Dict] = None,
self, file_name: str=None, trainer_config: Optional[Dict] = None,
):
if trainer_config is None:
trainer_config = self.katrain.config("trainer", {})
save_feedback = trainer_config.get("save_feedback", False)
eval_thresholds = trainer_config["eval_thresholds"]
print(trainer_config)
save_analysis = trainer_config.get("save_analysis", False)
def player_name(player_info):
@@ -324,20 +328,6 @@ class Game:
if save_analysis:
x_properties["KTV"] = ANALYSIS_FORMAT_VERSION
self.root.properties = {**root_properties, **{k: [v] for k, v in x_properties.items()}}
player_names = {bw: re.sub(r"['<>:\"/\\|?*]", "", self.root.get_property("P" + bw, bw)) for bw in "BW"}
base_game_name = f"katrain_{player_names['B']} vs {player_names['W']}"
game_name = f"{base_game_name} {self.game_id}"
if (
self.loaded_from_file
and base_game_name in self.loaded_from_file
and PROGRAM_NAME in self.root.get_property("AP", "")
and self.loaded_from_file.endswith("sgf")
):
file_name = self.loaded_from_file
else:
file_name = os.path.abspath(os.path.join(path, f"{game_name}.sgf"))
os.makedirs(os.path.dirname(file_name), exist_ok=True)
show_dots_for = {
bw: trainer_config.get("eval_show_ai", True) or self.katrain.players_info[bw].human for bw in "BW"
@@ -348,6 +338,8 @@ class Game:
eval_thresholds=eval_thresholds,
save_analysis=save_analysis,
)
file_name = file_name or self.generate_filename()
os.makedirs(os.path.dirname(file_name), exist_ok=True)
with open(file_name, "w", encoding="utf-8") as f:
f.write(sgf)
self.root.properties = root_properties
+3 -3
View File
@@ -950,9 +950,9 @@
on_action: root.katrain("save-game")
MainMenuItem:
text: i18n._('menu:save-as')
icon: 'img/Save-Game.png'
shortcut: 'Ctrl-Shift-S'
on_action: root.katrain("save-game-as")
icon: 'img/Save-Game-As.png'
shortcut: 'Ctrl-D'
on_action: root.katrain("save-game-as-popup")
MainMenuItem:
text: i18n._('menu:load')
icon: 'img/Load-Game.png'
+14 -2
View File
@@ -669,13 +669,25 @@ class LoadSGFPopup(BoxLayout):
super().__init__(**kwargs)
app = MDApp.get_running_app()
self.filesel.favorites = [
(os.path.abspath(app.gui.config("general/sgf_load")), "Last Used Dir"),
(os.path.abspath(app.gui.config("general/sgf_save")), "SGF Save Dir"),
(os.path.abspath(app.gui.config("general/sgf_load")), "Last Load Dir"),
(os.path.abspath(app.gui.config("general/sgf_save")), "Last Save Dir"),
]
self.filesel.path = os.path.abspath(os.path.expanduser(app.gui.config("general/sgf_load")))
self.filesel.select_string = i18n._("Load File")
class SaveSGFPopup(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
app = MDApp.get_running_app()
self.filesel.favorites = [
(os.path.abspath(app.gui.config("general/sgf_load")), "Last Load Dir"),
(os.path.abspath(app.gui.config("general/sgf_save")), "Last Save Dir"),
]
self.filesel.path = os.path.abspath(os.path.expanduser(MDApp.get_running_app().gui.config("general/sgf_save")))
self.filesel.select_string = i18n._("Save File")
class ReAnalyzeGamePopup(BoxLayout):
katrain = ObjectProperty(None)
popup = ObjectProperty(None)
Binary file not shown.
@@ -727,3 +727,18 @@ msgstr "Cache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -774,3 +774,18 @@ msgstr ""
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -293,6 +293,18 @@ msgstr "Your SGF notes for this position here."
msgid "load sgf title"
msgstr "Load SGF File to Analyze"
# sgf load button
msgid "Load File"
msgstr "Load File"
# sgf save as button
msgid "Save File"
msgstr "Save File"
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
msgid "load sgf fast analysis"
msgstr "Use fast analysis"
Binary file not shown.
@@ -787,3 +787,18 @@ msgstr "Cache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -813,3 +813,18 @@ msgstr "Cache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -766,3 +766,18 @@ msgstr "Cache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -741,3 +741,18 @@ msgstr "ache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.
@@ -775,3 +775,18 @@ msgstr "Cache analysis in SGF"
#. TODO
msgid "menu:save-as"
msgstr "Save Game As..."
#. TODO
# sgf load button
msgid "Load File"
msgstr "Load File"
#. TODO
# sgf save popup
msgid "save sgf title"
msgstr "Save SGF File"
#. TODO
# sgf save as button
msgid "Save File"
msgstr "Save File"
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

+11 -6
View File
@@ -181,13 +181,8 @@
orientation: 'horizontal'
GridLayout:
cols: 2
rows: 5
rows: 4
spacing: CP_SPACING
DescriptionLabel:
text: i18n._("general:sgf_save")
AnchorLayout:
LabelledPathInput:
input_property: "general/sgf_save"
DescriptionLabel:
text: i18n._('count down sound')
AnchorLayout:
@@ -622,3 +617,13 @@
filters: ["*.sgf","*.gib","*.ngf"]
path: "."
size_hint: 1,7
<SaveSGFPopup>:
filesel: filesel
orientation: 'vertical'
I18NFileBrowser:
id: filesel
multiselect: False
filters: ["*.sgf","*.gib","*.ngf"]
path: "."
size_hint: 1,7