german fixes, menu improvement

This commit is contained in:
Sander Land committed 2020-06-06 20:39:25 +02:00
1 parent 046847da1f
commit 1e90f4f8db
16 files changed
+196 -163

No files matched your search

+3 -2
View File
@@ -3,9 +3,10 @@ Sander Land
Many thanks to these additional authors:
Matthew Allred ("Kameone") for design of the v1.1 UI and providing MacOS installation instructions.
"isty2e" for Korean translation.
"Dontbtme" for detailed feedback and early testing of v1.0, and French translation.
"isty2e" for the Korean translation.
"Dontbtme" for detailed feedback and early testing of v1.0, and the French translation.
"bale-go" for implementing and calibrating the 'calibrated rank' AI.
"isty2e" for the German translation.
Additional thanks to:
"Seventeen" for explanatory youtube videos.
+3 -1
View File
@@ -4,7 +4,9 @@ This repository includes:
For on related licenses for these binaries and libraries see https://github.com/lightvector/KataGo
2. Icons from www.flaticon.com, used with permission with the following attributions:
- Save game/Load game/Elements of the configure icons/Flag icons: derived from work by Freepik from www.flaticon.com
- Equalize icon: derived from work by bqlqn from www.flaticon.com
- Other Menu icons and Flag icons: derived from work by Freepik from www.flaticon.com
3. The True Type Font DIGITAL-7 version 1.02 by Sizenko Alexander, which is free for non-commercial use.
+36 -34
View File
@@ -1,8 +1,5 @@
# first, logging level lower
import os
from kivy.base import ExceptionHandler, ExceptionManager
os.environ["KCFG_KIVY_LOG_LEVEL"] = os.environ.get("KCFG_KIVY_LOG_LEVEL", "warning")
os.environ['KIVY_AUDIO'] = "sdl2" # force working audio
@@ -36,6 +33,7 @@ import traceback
from queue import Queue
import webbrowser
from kivy.base import ExceptionHandler, ExceptionManager
from kivy.app import App
from kivy.core.clipboard import Clipboard
from kivy.lang import Builder
@@ -120,36 +118,7 @@ class KaTrainGui(Screen, KaTrainBase):
threading.Thread(target=self._message_loop_thread, daemon=True).start()
self._do_new_game()
def update_state(
self, redraw_board=False
): # is called after every message and on receiving analyses and config changes
# AI and Trainer/auto-undo handlers
cn = self.game and self.game.current_node
if not cn:
return
last_player, next_player = self.players_info[cn.player], self.players_info[cn.next_player]
if self.play_analyze_mode == MODE_PLAY:
teaching_undo = cn.player and last_player.being_taught
if (
teaching_undo
and cn.analysis_ready
and cn.parent
and cn.parent.analysis_ready
and not cn.children
and not self.game.ended
):
self.game.analyze_undo(cn) # not via message loop
if (
cn.analysis_ready
and next_player.ai
and not cn.children
and not self.game.ended
and not (teaching_undo and cn.auto_undo is None)
):
self._do_ai_move(
cn
) # cn mismatch stops this if undo fired. avoid message loop here or fires repeatedly.
def update_gui(self,cn,redraw_board=False):
# Handle prisoners and next player display
prisoners = self.game.prisoner_count
top, bot = [w.__self__ for w in self.board_controls.circles] # no weakref
@@ -177,11 +146,44 @@ class KaTrainGui(Screen, KaTrainBase):
# redraw
if redraw_board:
Clock.schedule_once(self.board_gui.draw_board, -1)
self.board_gui.draw_board()
self.board_gui.redraw_board_contents_trigger()
self.controls.update_evaluation()
self.controls.update_timer(1)
def update_state(
self, redraw_board=False
): # is called after every message and on receiving analyses and config changes
# AI and Trainer/auto-undo handlers
if not self.game or not self.game.current_node:
return
cn = self.game.current_node
last_player, next_player = self.players_info[cn.player], self.players_info[cn.next_player]
if self.play_analyze_mode == MODE_PLAY:
teaching_undo = cn.player and last_player.being_taught
if (
teaching_undo
and cn.analysis_ready
and cn.parent
and cn.parent.analysis_ready
and not cn.children
and not self.game.ended
):
self.game.analyze_undo(cn) # not via message loop
if (
cn.analysis_ready
and next_player.ai
and not cn.children
and not self.game.ended
and not (teaching_undo and cn.auto_undo is None)
):
self._do_ai_move(
cn
) # cn mismatch stops this if undo fired. avoid message loop here or fires repeatedly.
Clock.schedule_once(lambda _dt: self.update_gui(cn,redraw_board=redraw_board),-1)
def update_player(self, bw, **kwargs):
super().update_player(bw, **kwargs)
if self.controls:
+84 -46
View File
@@ -17,7 +17,6 @@
#:import BOX_BACKGROUND_COLOR katrain.gui.style.BOX_BACKGROUND_COLOR
#:import TEXT_COLOR katrain.gui.style.TEXT_COLOR
#:import BOX_BACKGROUND_COLOR katrain.gui.style.BOX_BACKGROUND_COLOR
#:set SPINNER_OPTION_COLOR [64 / 255, 85 / 255, 110 / 255, 1]
#:set BLACK [0.05,0.05,0.05,1]
@@ -139,7 +138,7 @@
Color:
rgba: LIGHTGREY
Line
points: self.pos[0],self.pos[1],self.pos[0]+self.width,self.pos[1]
points: self.x,self.y,self.x+self.width,self.y
width: 1
<I18NSpinner>:
@@ -688,6 +687,43 @@
size_hint_y: 1e-9 # takes up remaining space if info is closed
<MenuItem>
font_size: self.height * 0.5
size_hint_y: None
height: 50
background_color: BOX_BACKGROUND_COLOR
content_width: icon.width + label.texture_size[0] * 1.33
MDFloatLayout:
id: icon
size_hint: None, 1
width: self.height + 16
Image:
id:image
source: root.icon
mipmap: True
size_hint: 0.7,0.7
pos_hint: {'center_y': 0.5,'center_x': 0.5}
AnchorLayout:
size_hint_x: 1
anchor_x: 'left'
Label:
id: label
text: root.text
size: self.texture_size
size_hint: None, None
font_size: root.font_size
font_name: root.font_name
color: WHITE
Label:
text: root.shortcut
halign: 'left'
valign: 'middle'
size_hint_x: 1/3
font_size: root.font_size
font_name: root.font_name
color: LIGHTGREY
<AnalysisToggle>:
adaptive_width: True
spacing: CP_SPACING
@@ -711,19 +747,45 @@
active: root.default_active
on_active: if app.gui: app.gui.update_state()
<AnalysisDropdownMenu>:
background_color: BOX_BACKGROUND_COLOR
opening_time: 0.1
width_mult: 1.25
<AnalysisMenuItem@MenuItem>:
on_close: app.gui.analysis_controls.close_dropdown()
background_color: SPINNER_OPTION_COLOR
height: 45
canvas.before:
Color:
rgba: WHITE
Line:
points: self.x,self.y, self.x,self.y+self.height
Color:
rgba: LIGHTGREY
Line
points: self.x,self.y,self.x+self.width,self.y
width: 1
<AnalysisDropdownMenuRightContent>:
width: 0
Label:
id: label
size: dp(30)
font_size: root.font_size
text: root.text
color: LIGHTGREY
<AnalysisDropDown>:
width: 50
katrain: app.gui
AnalysisMenuItem:
text: i18n._("analysis:extra")
icon: 'img/Extra.png'
shortcut: 'a'
on_action: root.katrain("analyze-extra", "extra")
AnalysisMenuItem:
text: i18n._("analysis:equalize")
icon: 'img/Equalize.png'
shortcut: 's'
on_action: root.katrain("analyze-extra", "equalize")
AnalysisMenuItem:
text: i18n._("analysis:sweep")
icon: 'img/Sweep.png'
shortcut: 'd'
on_action: root.katrain("analyze-extra", "sweep")
AnalysisMenuItem:
text: i18n._("analysis:aimove")
icon: 'img/ai.png'
shortcut: 'enter'
on_action: root.katrain("ai-move")
<AnalysisControls>:
@@ -764,45 +826,19 @@
AnalysisToggle:
id: ownership
text: i18n._('analysis:territory')
AutoSizedRoundedRectangleButton:
AutoSizedRectangleButton:
background_color: BOX_BACKGROUND_COLOR
size_hint_y: 0.5
id: analysis_button
on_press: root.open_analysis_menu()
on_release: root.toggle_dropdown()
text: i18n._("btn:Analyze")
pos_hint: {'center_y':0.5}
<MainMenuItem>
font_size: self.height * 0.5
size_hint_y: None
<MainMenuItem@MenuItem>
on_close: app.gui.nav_drawer.set_state("close")
height: self.parent.item_height or 50
background_color: BOX_BACKGROUND_COLOR
MDFloatLayout:
size_hint: None, 1
width: self.height + 16
Image:
id:image
source: root.icon
mipmap: True
size_hint: 0.7,0.7
pos_hint: {'center_y': 0.5,'center_x': 0.5}
Label:
text: root.text
text_size: self.size
size_hint_x: 1
halign: 'left'
valign: 'middle'
font_size: root.font_size
font_name: root.font_name
color: WHITE
Label:
text: root.shortcut
halign: 'left'
valign: 'middle'
size_hint_x: 1/3
font_size: root.font_size
font_name: root.font_name
color: LIGHTGREY
<LangButton@TransparentIconButton>
@@ -999,6 +1035,8 @@
id: analyze
on_state: app.gui.update_state()
<KaTrainGui>:
board_gui: board_gui
controls: controls
+22 -34
View File
@@ -7,17 +7,16 @@ from kivy.clock import Clock
from kivy.core.window import Window
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Ellipse, Line, Rectangle
from kivy.properties import ListProperty
from kivy.properties import ListProperty, ObjectProperty, BooleanProperty
from kivy.uix.dropdown import DropDown
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.menu import MDDropdownMenu
from katrain.core.constants import MODE_PLAY, OUTPUT_DEBUG
from katrain.core.game import Move
from katrain.core.lang import i18n
from katrain.core.utils import evaluation_class, var_to_grid
from katrain.gui.kivyutils import draw_circle, draw_text
from katrain.gui.kivyutils import draw_circle, draw_text, BackgroundMixin
from katrain.gui.style import *
@@ -468,46 +467,35 @@ class BadukPanWidget(Widget):
self.set_animating_pv(pv_str[1:].split(" "), self.katrain.controls.active_comment_node.parent)
class AnalysisDropdownMenu(MDDropdownMenu):
def create_menu_items(self):
super().create_menu_items()
for widget in self.menu.ids.box.children:
try:
widget.ids._text_container.children[2].font_name = i18n.font_name
except: # TODO not use this terrible widget
class AnalysisDropDown(DropDown):
pass
class AnalysisControls(MDFloatLayout):
ANALYSIS_OPTIONS = ["analysis:extra", "analysis:equalize", "analysis:sweep", "analysis:aimove"]
ANALYSIS_SHORTCUTS = ["a", "s", "d", "enter"]
dropdown = ObjectProperty(None)
is_open = BooleanProperty(False)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.analysis_menu = None
MDApp.get_running_app().bind(language=lambda *_args: Clock.schedule_once(self.build_menu))
Clock.schedule_once(self.build_menu, 0)
self.build_dropdown()
def build_menu(self, _dt):
menu_items = [
{"text": i18n._(text) + f" ({shortcut})"}
for text, shortcut in zip(self.ANALYSIS_OPTIONS, self.ANALYSIS_SHORTCUTS)
]
self.analysis_menu = AnalysisDropdownMenu(
caller=self.analysis_button, items=menu_items, width_mult=6, use_icon_item=False, callback=self.action
)
def on_is_open(self, instance, value):
if value:
max_content_width = max(option.content_width for option in self.dropdown.container.children)
self.dropdown.width = max_content_width
self.dropdown.open(self.analysis_button)
elif self.dropdown.attach_to:
self.dropdown.dismiss()
def action(self, item):
katrain = MDApp.get_running_app().gui
shortcuts = katrain.shortcuts
for text, shortcut in zip(self.ANALYSIS_OPTIONS, self.ANALYSIS_SHORTCUTS):
if item.text.startswith(i18n._(text)):
katrain(*shortcuts[shortcut])
def close_dropdown(self, *largs):
self.is_open = False
def open_analysis_menu(self):
while not self.analysis_menu:
time.sleep(0.01)
self.analysis_menu.open()
def toggle_dropdown(self, *largs):
self.is_open = not self.is_open
def build_dropdown(self):
self.dropdown = AnalysisDropDown(auto_width=False)
self.dropdown.bind(on_dismiss=self.close_dropdown)
class BadukPanControls(MDFloatLayout):
+1 -4
View File
@@ -2,13 +2,10 @@ import time
from kivy.clock import Clock
from kivy.core.audio import SoundLoader
from kivy.properties import ObjectProperty, ListProperty
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from katrain.core.lang import i18n
from katrain.core.constants import MODE_PLAY, MODE_ANALYZE
+6 -3
View File
@@ -317,21 +317,24 @@ class AnalysisToggle(MDBoxLayout):
return self.checkbox.active
class MainMenuItem(RectangularRippleBehavior, LeftButtonBehavior, MDBoxLayout, BackgroundMixin):
__events__ = ["on_action"]
class MenuItem(RectangularRippleBehavior, LeftButtonBehavior, MDBoxLayout, BackgroundMixin):
__events__ = ["on_action","on_close"]
icon = StringProperty("")
text = StringProperty("")
shortcut = StringProperty("")
font_name = StringProperty(DEFAULT_FONT)
content_width = NumericProperty(100)
def on_left_release(self):
self.anim_complete() # kill ripple
MDApp.get_running_app().gui.nav_drawer.set_state("close")
self.dispatch("on_close")
self.dispatch("on_action")
def on_action(self):
pass
def on_close(self):
pass
class CollapsablePanelHeader(MDBoxLayout):
pass
+5
View File
@@ -298,8 +298,13 @@ class AIPopup(QuickConfigGui):
class ConfigPopup(QuickConfigGui):
def __init__(self, katrain):
super().__init__(katrain)
def set_config_hint(*args):
self.configfile.text = i18n._("config file path").format(file=katrain.config_file)
set_config_hint()
MDApp.get_running_app().bind(language=set_config_hint)
def update_config(self, save_to_file=True):
updated = super().update_config(save_to_file=save_to_file)
self.katrain.debug_level = self.katrain.config("general/debug_level", OUTPUT_INFO)
Binary file not shown.
+35 -38
View File
@@ -113,9 +113,8 @@ msgstr ""
msgid "ai-ponder"
msgstr ""
"Dies zeigt den Enginestatus an von grün (Leerlauf) bis orange "
"(Zugberechnung).Es wird rot, wenn die Engine abgestürzt ist oder nicht "
"starten konnte."
"Zeigt den Enginestatus an von grün (Leerlauf) bis orange(Zugberechnung). Ist"
" rot, wenn die Engine abgestürzt ist oder nicht starten konnte."
#. undo button on the right
msgid "undo-button-text"
@@ -167,13 +166,13 @@ msgid "btn:Analysis"
msgstr "Analyse"
msgid "btn:Analyze"
msgstr "Analyse Optionen"
msgstr "Analyseoptionen"
msgid "stats:winrate"
msgstr "Gewinnrate"
msgid "stats:score"
msgstr "Geschätzes Ergebnis"
msgstr "Ergebnis"
msgid "stats:pointslost"
msgstr "Punkte verloren"
@@ -214,7 +213,7 @@ msgid "Info:policy rank"
msgstr "Zug war #{rank} gemäss Policy ({probability:.2%})."
msgid "Info:policy best"
msgstr "Bester Policy Zug war {move} ({probability:.1%})."
msgstr "Bester Policy-Zug war {move} ({probability:.1%})."
msgid "Info:teaching undo"
msgstr "Zug wurde automatisch im Lehrmodus zurückgenommen."
@@ -242,11 +241,11 @@ msgid "load sgf fast analysis"
msgstr "Schnelle Analyse verwenden"
msgid "load sgf rewind"
msgstr "Zum Start zurückspulen"
msgstr "Am Anfang beginnen"
# timer settings from here
msgid "timer settings"
msgstr "Timer Einstellungen Anpassen"
msgstr "Timereinstellungen Anpassen"
msgid "byoyomi length"
msgstr "Zeit pro Byo-yomi Periode"
@@ -309,7 +308,7 @@ msgstr "Neues Spiel Starten"
# teacher settings from here
msgid "teacher settings"
msgstr "Lehrereinstellungen Bearbeiten"
msgstr "Übungsspieleinstellungen Bearbeiten"
msgid "point loss threshold"
msgstr "Punktverlust grösser als"
@@ -318,7 +317,7 @@ msgid "num undos"
msgstr "Anzahl der Undos"
msgid "dot color"
msgstr "Farbe (konstant)"
msgstr "Farbe (fix)"
msgid "show dots"
msgstr "Dots zeigen"
@@ -343,7 +342,7 @@ msgstr ""
#. submit button
msgid "update teacher"
msgstr "Feedback Einstellungen aktualisieren"
msgstr "Feedbackeinstellungen aktualisieren"
# main config settings
msgid "restarting engine"
@@ -369,7 +368,7 @@ msgid "engine:katago"
msgstr "Pfad zur KataGo Datei"
msgid "engine:katago:hint"
msgstr "Leer lassen, um beigefügte Datei zu verwenden."
msgstr "Leer = beigefügte Datei verwenden."
msgid "engine:model"
msgstr "Pfad zur KataGo Model Datei"
@@ -475,7 +474,7 @@ msgstr "KataGo"
msgid "aihelp:default"
msgstr ""
"Spielstärkste KataGo AI. Spielstärke wird von `max visits` und `model`in den"
" allgemeinen Einstellungen Bereich `engine` und dem Engine-"
" allgemeinen Einstellungen im Bereich `engine` und dem Engine-"
"Konfigurationsfile bestimmt. Hier gibt es sonst keine Optionen."
msgid "ai:jigo"
@@ -487,7 +486,7 @@ msgstr ""
"weitere Einschränkungen."
msgid "ai:scoreloss"
msgstr "Punktverluste"
msgstr "Punktverlust"
msgid "aihelp:scoreloss"
msgstr ""
@@ -499,9 +498,9 @@ msgstr "Policy"
msgid "aihelp:policy"
msgstr ""
"Wählt den besten Zug vom Policy Netzwerk ohne Analyse. Die Stärke ist am "
"Wählt den besten Zug vom Policy-Netzwerk ohne Analyse. Die Stärke ist am "
"meisten von der `model` Einstellung in den Engine Einstellungen abhängig. "
"Die Eröffnungs-züge Einstellung bestimmt wie viele Züge der Eröffnung "
"Die `opening_moves` Einstellung bestimmt wie viele Züge der Eröffnung "
"zufällig sind."
msgid "ai:p:weighted"
@@ -509,11 +508,11 @@ msgstr "Policy Gewichtet"
msgid "aihelp:p:weighted"
msgstr ""
"Wählt den Zug gemäss der Policy Wahrscheinlichkeit, beeinflusst durch "
"Wählt den Zug gemäss der Policy-Wahrscheinlichkeit, beeinflusst durch "
"`weaken_fac` wie wahrscheinlich schlechtere Züge gespielt werden. Ein hoher "
"negativer Wert spielt wie die `Policy` AI. `pick_override` legt fest, wann "
"der beste Zug gewählt wird ohne Zufall und `lower_bound` bestimmt die untere"
" Grenze des erlaubten Policy Wertes."
" Grenze des erlaubten Policy-Wertes."
msgid "ai:p:pick"
msgstr "Blinde Policy"
@@ -522,7 +521,7 @@ msgid "aihelp:p:pick"
msgstr ""
"Wählt `pick_n + pick_frac * <number of legal moves>` gewichtete Züge "
"zufälligund spielt den Besten. Spielt wie die Policy AI, wenn `pick_frac=1`."
" Spielt besten Zug, wenn Policy Wert höher als `pick_override` ist, um "
" Spielt besten Zug, wenn Policy-Wert höher als `pick_override` ist, um "
"offensichtliche Fehler zu vermeiden."
msgid "ai:p:local"
@@ -530,8 +529,8 @@ msgstr "Lokaler Stil"
msgid "aihelp:p:local"
msgstr ""
"Wählt `pick_n + pick_frac * <number of legal moves>` gewichtete Züge hin "
"zumletzten Zug und spielt den Besten. Spielt besten Zug, wenn Policy Wert "
"Wählt `pick_n + pick_frac * <number of legal moves>` gewichtete Züge nahedem"
" letzten Zug und spielt den Besten. Spielt besten Zug, wenn Policy-Wert "
"höher als`pick_override` ist, um offensichtliche Fehler zu vermeiden."
msgid "ai:p:tenuki"
@@ -539,39 +538,37 @@ msgstr "Tenuki Stil"
msgid "aihelp:p:tenuki"
msgstr ""
"Wählt `pick_n + pick_frac * <number of legal moves>` gewichtete Züge weg "
"vomletzten Zug und spielt den Besten. Spielt besten Zug, wenn Policy Wert "
"höher als`pick_override` ist, um offensichtliche Fehler zu vermeiden. Eine "
"höhere `stddev`führt zu weiter entfernten Zügen."
"Wählt `pick_n + pick_frac * <number of legal moves>` gewichtete Züge "
"fernvomletzten Zug und spielt den Besten. Spielt besten Zug, wenn Policy-"
"Wert höher als`pick_override` ist, um offensichtliche Fehler zu vermeiden. "
"Eine höhere `stddev`führt zu weiter entfernten Zügen."
msgid "ai:p:influence"
msgstr "Einfluss Stil"
msgstr "Einflussstil"
msgid "aihelp:p:influence"
msgstr ""
"Wählt Züge oberhalb des Grenzwertes und spielt den Besten.Erhöht den "
"`line_weight`, um Züge nahe der Ecken zu bestrafen.Stoppt die Strategie nach"
" dem der 'endgame' Teil des Brettes gefüllt ist."
"Wählt Züge oberhalb des Grenzwertes und spielt den Besten.Erhöhe "
"`line_weight`,um Züge nahe der Ecken mehr zu bestrafen.Stoppt die Strategie "
"nach dem der 'endgame' Anteil des Brettes gefüllt ist."
msgid "ai:p:territory"
msgstr "Gebietsstil"
msgid "aihelp:p:territory"
msgstr ""
"Wählt Züge unterhalb des Grenzwertes und spielt den Besten.Erhöht den "
"`line_weight`, um Züge nahe der Mitte zu bestrafen.Stoppt die Strategie nach"
" dem der 'endgame' Teil des Brettes gefüllt ist."
"Wählt Züge unterhalb des Grenzwertes und spielt den Besten.Erhöhe "
"`line_weight`,um Züge nahe der Mitte mehr zu bestrafen.Stoppt die Strategie "
"nach dem der 'endgame' Anteil des Brettes gefüllt ist."
#. TODO
msgid "aihelp:p:rank"
msgstr ""
"Picks moves at random from a limited selection of moves and plays the best "
"one. Stronger settings select the best move from a larger selection. Since "
"there is no 0 kyu/dan, 3 dan = -2 kyu."
"Wählt zufällige Züge aus einer beschränkten Auswahl an Zügen und spieltden "
"Besten. Stärkere Einstellungen wählen den besten Zug aus einer grösseren "
"Auswahl. Da es keinen 0 Kyu/Dan gibt, ist 3 Dan = -2 Kyu."
#. TODO
msgid "ai:p:rank"
msgstr "Calibrated Rank"
msgstr "Kalibrierter Rang"
#. TODO
msgid "tab:info-details"
Binary file not shown.
@@ -35,7 +35,7 @@ msgid "menu:lang"
msgstr "Language"
msgid "menu:support"
msgstr "Support"
msgstr "Contribute"
msgid "menu:manual"
msgstr "Manual"
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB