beter graph and i18n
This commit is contained in:
1 parent
738578ee5a
commit
c424541b35
15 files changed
+330
-179
No files matched your search
@@ -0,0 +1,40 @@
|
|||||||
|
import os
|
||||||
|
import polib
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
localedir = "katrain/i18n/locales"
|
||||||
|
locales = set(os.listdir(localedir))
|
||||||
|
print("locales found:",locales)
|
||||||
|
|
||||||
|
strings_to_langs = defaultdict(dict)
|
||||||
|
lang_to_strings = defaultdict(set)
|
||||||
|
|
||||||
|
DEFAULT_LANG = "en"
|
||||||
|
|
||||||
|
po = {}
|
||||||
|
for lang in locales:
|
||||||
|
pofile = os.path.join(localedir, lang, 'LC_MESSAGES', 'katrain.po')
|
||||||
|
po[lang] = polib.pofile(pofile)
|
||||||
|
for entry in po[lang].translated_entries():
|
||||||
|
if 'TODO' in entry.comment:
|
||||||
|
print(lang,'/',entry.msgid,'is TODO')
|
||||||
|
else:
|
||||||
|
strings_to_langs[entry.msgid][lang] = entry.msgstr
|
||||||
|
lang_to_strings[lang].add(entry.msgid)
|
||||||
|
|
||||||
|
|
||||||
|
for lang in locales:
|
||||||
|
for msgid in strings_to_langs.keys() - lang_to_strings[lang]:
|
||||||
|
if lang==DEFAULT_LANG:
|
||||||
|
print("Message id",msgid,"found as ",strings_to_langs[msgid],"but missing in default",DEFAULT_LANG)
|
||||||
|
elif DEFAULT_LANG in strings_to_langs[msgid]:
|
||||||
|
print("Message id", msgid, "missing in ",lang,'-> Adding it from',DEFAULT_LANG)
|
||||||
|
entry = polib.POEntry(msgid=msgid,msgstr=strings_to_langs[msgid][DEFAULT_LANG],comment="TODO")
|
||||||
|
po[lang].append(entry)
|
||||||
|
else:
|
||||||
|
print(f"MISSING IN DEFAULT AND {lang}",strings_to_langs[msgid])
|
||||||
|
po[lang].save(pofile)
|
||||||
|
mofile = pofile.replace('.po', '.mo')
|
||||||
|
po[lang].save_as_mofile(mofile)
|
||||||
|
print('Fixed',pofile,'and converted ->',mofile)
|
||||||
|
|
||||||
+4
-4
@@ -29,7 +29,7 @@ from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
|
|||||||
from katrain.core.sgf_parser import Move, ParseError
|
from katrain.core.sgf_parser import Move, ParseError
|
||||||
from katrain.gui.kivyutils import *
|
from katrain.gui.kivyutils import *
|
||||||
from katrain.gui.graph import ScoreGraph
|
from katrain.gui.graph import ScoreGraph
|
||||||
from katrain.gui.badukpan import BadukPanWidget
|
from katrain.gui.badukpan import BadukPanWidget, AnalysisControls, BadukPanControls
|
||||||
from katrain.gui.controlspanel import ControlsPanel, RightButtonControls
|
from katrain.gui.controlspanel import ControlsPanel, RightButtonControls
|
||||||
from katrain.gui.popups import NewGamePopup, ConfigPopup, LoadSGFPopup
|
from katrain.gui.popups import NewGamePopup, ConfigPopup, LoadSGFPopup
|
||||||
from katrain.core.common import Lang
|
from katrain.core.common import Lang
|
||||||
@@ -294,9 +294,9 @@ class KaTrainGui(Screen):
|
|||||||
"r": self.analysis_controls.ownership,
|
"r": self.analysis_controls.ownership,
|
||||||
"t": self.analysis_controls.policy,
|
"t": self.analysis_controls.policy,
|
||||||
"enter": ("ai-move",),
|
"enter": ("ai-move",),
|
||||||
"a": self.analysis_controls.analyze_extra,
|
"a": ("analyze-extra", "extra"),
|
||||||
"s": self.analysis_controls.analyze_equalize,
|
"s": ("analyze-extra", "equalize"),
|
||||||
"d": self.analysis_controls.analyze_sweep,
|
"d": ("analyze-extra", "sweep"),
|
||||||
"p": ("play", None),
|
"p": ("play", None),
|
||||||
"right": ("switch-branch", 1),
|
"right": ("switch-branch", 1),
|
||||||
"left": ("switch-branch", -1),
|
"left": ("switch-branch", -1),
|
||||||
|
|||||||
@@ -94,13 +94,24 @@ class GameNode(SGFNode):
|
|||||||
def analysis_ready(self):
|
def analysis_ready(self):
|
||||||
return self.analysis["root"] is not None
|
return self.analysis["root"] is not None
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def score(self) -> Optional[float]:
|
||||||
|
if self.analysis_ready:
|
||||||
|
return self.analysis["root"].get("scoreLead")
|
||||||
|
|
||||||
def format_score(self, score=None):
|
def format_score(self, score=None):
|
||||||
score = score or self.score
|
score = score or self.score
|
||||||
if score is not None:
|
if score is not None:
|
||||||
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
|
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
|
||||||
|
|
||||||
def format_win_rate(self, win_rate=None):
|
@property
|
||||||
win_rate = win_rate or self.analysis["root"].get("winrate")
|
def winrate(self) -> Optional[float]:
|
||||||
|
if self.analysis_ready:
|
||||||
|
return self.analysis["root"].get("winrate")
|
||||||
|
|
||||||
|
def format_winrate(self, win_rate=None):
|
||||||
|
win_rate = win_rate or self.winrate
|
||||||
if win_rate is not None:
|
if win_rate is not None:
|
||||||
return f"{'B' if win_rate > 0.5 else 'W'} {max(win_rate,1-win_rate):.1%}"
|
return f"{'B' if win_rate > 0.5 else 'W'} {max(win_rate,1-win_rate):.1%}"
|
||||||
|
|
||||||
@@ -120,7 +131,7 @@ class GameNode(SGFNode):
|
|||||||
score = self.score
|
score = self.score
|
||||||
if sgf:
|
if sgf:
|
||||||
text += f"Score: {self.format_score(score)}\n"
|
text += f"Score: {self.format_score(score)}\n"
|
||||||
text += f"Win Rate: {self.format_win_rate()}\n"
|
text += f"Win Rate: {self.format_winrate()}\n"
|
||||||
if self.parent and self.parent.analysis_ready:
|
if self.parent and self.parent.analysis_ready:
|
||||||
previous_top_move = self.parent.candidate_moves[0]
|
previous_top_move = self.parent.candidate_moves[0]
|
||||||
if sgf or hints:
|
if sgf or hints:
|
||||||
@@ -168,10 +179,6 @@ class GameNode(SGFNode):
|
|||||||
score = self.score
|
score = self.score
|
||||||
return self.player_sign(single_move.player) * (score - parent_parent_score)
|
return self.player_sign(single_move.player) * (score - parent_parent_score)
|
||||||
|
|
||||||
@property
|
|
||||||
def score(self) -> Optional[float]:
|
|
||||||
if self.analysis_ready:
|
|
||||||
return self.analysis["root"]["scoreLead"]
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def player_sign(player):
|
def player_sign(player):
|
||||||
|
|||||||
+99
-138
@@ -67,6 +67,7 @@
|
|||||||
|
|
||||||
<SizedMDBaseButton>:
|
<SizedMDBaseButton>:
|
||||||
text_color: WHITE
|
text_color: WHITE
|
||||||
|
md_bg_color: BOX_BACKGROUND_COLOR
|
||||||
label: label
|
label: label
|
||||||
Label:
|
Label:
|
||||||
id: label
|
id: label
|
||||||
@@ -74,7 +75,6 @@
|
|||||||
size_hint_x: None
|
size_hint_x: None
|
||||||
color: root.text_color
|
color: root.text_color
|
||||||
font_size: root.font_size
|
font_size: root.font_size
|
||||||
font_name: root.font_name or self.font_name
|
|
||||||
halign: root.halign
|
halign: root.halign
|
||||||
|
|
||||||
<SizedMDFlatButton>:
|
<SizedMDFlatButton>:
|
||||||
@@ -91,14 +91,25 @@
|
|||||||
|
|
||||||
<AutoSizedMDFlatRectangleButton>: # only wants height
|
<AutoSizedMDFlatRectangleButton>: # only wants height
|
||||||
width: self.label.texture_size[0] + self.hor_padding * 2
|
width: self.label.texture_size[0] + self.hor_padding * 2
|
||||||
|
font_size: 0.75 * self.height / len(self.label.text.split('\n'))
|
||||||
|
|
||||||
<AutoSizedMDFlatRectangleToggleButton>: # only wants height
|
<AutoSizedMDFlatRectangleToggleButton>: # only wants height
|
||||||
width: self.label.texture_size[0] + self.hor_padding * 2
|
width: self.label.texture_size[0] + self.hor_padding * 2
|
||||||
|
font_size: 0.75 * self.height / len(self.label.text.split('\n'))
|
||||||
|
|
||||||
<BGMDBoxLayout@MDBoxLayout+BackgroundColor>:
|
<BGMDBoxLayout@MDBoxLayout+BackgroundColor>:
|
||||||
background_color: BOX_BACKGROUND_COLOR
|
background_color: BOX_BACKGROUND_COLOR
|
||||||
|
|
||||||
|
<TransparentIconButton>:
|
||||||
|
background_normal: ''
|
||||||
|
background_color: (0,0,0,0)
|
||||||
|
icon_size: self.icon_size or [min(self.size[0],self.size[1]),min(self.size[0],self.size[1])]
|
||||||
|
Image:
|
||||||
|
size: root.icon_size
|
||||||
|
pos: [root.pos[i] + (root.size[i] - root.icon_size[i])/2 for i in [0,1]]
|
||||||
|
source: root.icon
|
||||||
|
mipmap: True
|
||||||
|
|
||||||
|
|
||||||
# -- old widgets
|
# -- old widgets
|
||||||
|
|
||||||
@@ -142,10 +153,6 @@
|
|||||||
<StyledToggleButton>:
|
<StyledToggleButton>:
|
||||||
max_lines: 1
|
max_lines: 1
|
||||||
|
|
||||||
<StyledTabButton@StyledToggleButton>:
|
|
||||||
bold: True
|
|
||||||
radius: (self.size[1]/3,self.size[1]/3,0,0)
|
|
||||||
|
|
||||||
<ToggleButtonContainer>:
|
<ToggleButtonContainer>:
|
||||||
|
|
||||||
<LabelledTextInput>:
|
<LabelledTextInput>:
|
||||||
@@ -183,17 +190,6 @@
|
|||||||
mipmap: True
|
mipmap: True
|
||||||
|
|
||||||
|
|
||||||
<TransparentIconButton>:
|
|
||||||
background_normal: ''
|
|
||||||
background_color: (0,0,0,0)
|
|
||||||
icon_size: self.icon_size or [min(self.size[0],self.size[1]),min(self.size[0],self.size[1])]
|
|
||||||
image: image
|
|
||||||
Image:
|
|
||||||
id: image
|
|
||||||
size: root.icon_size
|
|
||||||
pos: [root.pos[i] + (root.size[i] - root.icon_size[i])/2 for i in [0,1]]
|
|
||||||
source: root.icon
|
|
||||||
mipmap: True
|
|
||||||
|
|
||||||
<LightLabel>:
|
<LightLabel>:
|
||||||
color: TEXT_COLOR
|
color: TEXT_COLOR
|
||||||
@@ -269,63 +265,18 @@
|
|||||||
katrain: app.gui
|
katrain: app.gui
|
||||||
|
|
||||||
<BoardControlsButton@MDFillRoundFlatIconButton>:
|
<BoardControlsButton@MDFillRoundFlatIconButton>:
|
||||||
md_bg_color: BOX_BACKGROUND_COLOR
|
|
||||||
|
|
||||||
<Menu@BoxLayout>:
|
|
||||||
eval: eval
|
|
||||||
policy: policy
|
|
||||||
hints: hints
|
|
||||||
ownership: ownership
|
|
||||||
analyze_extra: analyze_extra
|
|
||||||
analyze_equalize: analyze_equalize
|
|
||||||
analyze_sweep: analyze_sweep
|
|
||||||
ButtonBoxHolder:
|
|
||||||
size_hint_y: INFO_BOX_HEIGHT * 0.75
|
|
||||||
ButtonBox:
|
|
||||||
RHSToggleButton:
|
|
||||||
id: eval
|
|
||||||
text: 'Dots'
|
|
||||||
color: WHITE
|
|
||||||
RHSToggleButton:
|
|
||||||
id: ownership
|
|
||||||
text: 'Territory'
|
|
||||||
color: WHITE
|
|
||||||
RHSToggleButton:
|
|
||||||
id: policy
|
|
||||||
text: 'Policy'
|
|
||||||
color: WHITE
|
|
||||||
RHSToggleButton:
|
|
||||||
id: hints
|
|
||||||
text: 'Top Moves'
|
|
||||||
color: WHITE
|
|
||||||
RHSButton:
|
|
||||||
id: analyze_extra
|
|
||||||
text: 'Extra'
|
|
||||||
tooltip_text: '[a]\nExtra analysis\nto increase accuracy\nof top move predictions\nand score difference'
|
|
||||||
on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","extra")
|
|
||||||
RHSButton:
|
|
||||||
id: analyze_equalize
|
|
||||||
text: 'Equalize'
|
|
||||||
tooltip_text: '[s]\nAnalysis of all\npredicted top moves\nwith the same accuracy'
|
|
||||||
on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","equalize")
|
|
||||||
RHSButton:
|
|
||||||
id: analyze_sweep
|
|
||||||
text: 'Sweep'
|
|
||||||
tooltip_text: '[d]\nFast analysis\nof all legal moves'
|
|
||||||
on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","sweep")
|
|
||||||
|
|
||||||
<NavIconButton@TransparentIconButton>:
|
<NavIconButton@TransparentIconButton>:
|
||||||
size_hint: 0.06, 0.5
|
size_hint: 0.06, 0.5
|
||||||
pos_hint: {'center_y': 0.5}
|
pos_hint: {'center_y': 0.5}
|
||||||
|
|
||||||
|
|
||||||
<BadukPanControls>:
|
<BadukPanControls>:
|
||||||
katrain: app.gui
|
katrain: app.gui
|
||||||
circles: [black_circle,white_circle]
|
circles: [black_circle,white_circle]
|
||||||
mid_circles_container: mid_circles_container
|
mid_circles_container: mid_circles_container
|
||||||
pass_btn: pass_btn
|
pass_btn: pass_btn
|
||||||
hamburger: hamburger
|
hamburger: hamburger
|
||||||
analysis_button: analysis_button
|
|
||||||
adaptive_height: True
|
adaptive_height: True
|
||||||
HamburgerButton:
|
HamburgerButton:
|
||||||
id: hamburger
|
id: hamburger
|
||||||
@@ -333,14 +284,13 @@
|
|||||||
width: self.height
|
width: self.height
|
||||||
pos_hint: {'x': 0}
|
pos_hint: {'x': 0}
|
||||||
on_press: app.gui.nav_drawer.set_state("open")
|
on_press: app.gui.nav_drawer.set_state("open")
|
||||||
StyledButton:
|
SizedMDFlatRectangleButton:
|
||||||
|
id: pass_btn
|
||||||
text: i18n._('pass-button-text')
|
text: i18n._('pass-button-text')
|
||||||
tooltip_text: i18n._('pass-button-tooltip')
|
tooltip_text: i18n._('pass-button-tooltip')
|
||||||
id: pass_btn
|
|
||||||
size_hint: None, 0.5
|
size_hint: None, 0.5
|
||||||
|
width: 2*self.height
|
||||||
pos_hint: {'x': 0.1,'center_y':0.5}
|
pos_hint: {'x': 0.1,'center_y':0.5}
|
||||||
width: self.height * 2
|
|
||||||
font_size: 0.6*self.size[1]
|
|
||||||
on_left_release: root.katrain("play",None)
|
on_left_release: root.katrain("play",None)
|
||||||
canvas.before:
|
canvas.before:
|
||||||
Color:
|
Color:
|
||||||
@@ -419,26 +369,12 @@
|
|||||||
on_press: root.katrain('redo',999)
|
on_press: root.katrain('redo',999)
|
||||||
NavIconButton:
|
NavIconButton:
|
||||||
icon: 'img/flaticon/route.png'
|
icon: 'img/flaticon/route.png'
|
||||||
StyledButton:
|
|
||||||
size_hint: None, 0.5
|
|
||||||
pos_hint: {'right': 1,'center_y':0.5}
|
|
||||||
width: self.height * 4
|
|
||||||
font_size: 0.6*self.size[1]
|
|
||||||
id: analysis_button
|
|
||||||
text: 'Analysis Settings'
|
|
||||||
icon: 'settings'
|
|
||||||
on_press: root.open_analysis_menu()
|
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: RED
|
|
||||||
Line:
|
|
||||||
rectangle: (*self.pos,*self.size)
|
|
||||||
width: 1
|
|
||||||
|
|
||||||
<HamburgerButton@MDFloatingActionButton>:
|
<HamburgerButton@TransparentIconButton>:
|
||||||
icon: 'menu'
|
icon: 'img/hamburger.png'
|
||||||
size_hint: None, 1
|
size_hint: None, 1
|
||||||
width: self.height
|
width: self.height
|
||||||
|
icon_size: [self.height * 0.8, self.height * 0.8]
|
||||||
|
|
||||||
# ---------- components of right pane -------
|
# ---------- components of right pane -------
|
||||||
|
|
||||||
@@ -527,7 +463,6 @@
|
|||||||
valign: 'bottom'
|
valign: 'bottom'
|
||||||
halign: 'left'
|
halign: 'left'
|
||||||
text: '+0'
|
text: '+0'
|
||||||
color: SCORE_COLOR
|
|
||||||
size: self.texture_size
|
size: self.texture_size
|
||||||
|
|
||||||
<ScoreGraph>:
|
<ScoreGraph>:
|
||||||
@@ -536,60 +471,82 @@
|
|||||||
bhalf: root.pos[1]+self.height*0.75
|
bhalf: root.pos[1]+self.height*0.75
|
||||||
mid: root.pos[1]+self.height*0.5
|
mid: root.pos[1]+self.height*0.5
|
||||||
right_edge: root.pos[0] + root.width
|
right_edge: root.pos[0] + root.width
|
||||||
|
marker_font_size: 0.1 * root.height
|
||||||
canvas:
|
canvas:
|
||||||
Color:
|
Color:
|
||||||
rgba: GRAPH_CENTER_COLOR
|
rgba: GRAPH_CENTER_COLOR
|
||||||
Line:
|
Line:
|
||||||
points: [root.pos[0],root.whalf,root.pos[0]+root.width,root.whalf]
|
points: [root.pos[0],root.whalf,root.pos[0]+root.width,root.whalf]
|
||||||
width: 1
|
width: 1
|
||||||
dashes: [2,2]
|
# dashes: [2,2]
|
||||||
Line:
|
Line:
|
||||||
points: [root.pos[0],root.mid,root.pos[0]+root.width,root.mid]
|
points: [root.pos[0],root.mid,root.pos[0]+root.width,root.mid]
|
||||||
width: 1
|
width: 1
|
||||||
dashes: [4,4]
|
# dashes: [4,4]
|
||||||
Line:
|
Line:
|
||||||
points: [root.pos[0],root.bhalf,root.pos[0]+root.width,root.bhalf]
|
points: [root.pos[0],root.bhalf,root.pos[0]+root.width,root.bhalf]
|
||||||
width: 1
|
width: 1
|
||||||
dashes: [2,2]
|
# dashes: [2,2]
|
||||||
canvas.after:
|
canvas.after:
|
||||||
Color:
|
Color:
|
||||||
rgba: SCORE_COLOR
|
rgba: SCORE_COLOR
|
||||||
Line:
|
Line:
|
||||||
points: root.score_points
|
points: root.score_points if root.show_score else []
|
||||||
width: 1.1
|
width: 1.1
|
||||||
Color:
|
Color:
|
||||||
rgba: WINRATE_COLOR
|
rgba: WINRATE_COLOR
|
||||||
Line:
|
Line:
|
||||||
points: root.winrate_points
|
points: root.winrate_points if root.show_winrate else []
|
||||||
width: 1.1
|
width: 1.1
|
||||||
|
|
||||||
Color:
|
Color:
|
||||||
rgba: GRAPH_DOT_COLOR
|
rgba: GRAPH_DOT_COLOR
|
||||||
Ellipse:
|
Ellipse:
|
||||||
id: dot
|
id: dot
|
||||||
pos: root.dot_pos
|
pos: root.dot_pos
|
||||||
size: self.highlight_size,self.highlight_size
|
size: self.highlight_size,self.highlight_size
|
||||||
|
# score ticks
|
||||||
GraphMarkerLabel:
|
GraphMarkerLabel:
|
||||||
font_size: 0.1 * root.height
|
font_size: root.marker_font_size
|
||||||
id: range_label_top
|
color: SCORE_COLOR
|
||||||
pos: root.right_edge - self.width-1, root.pos[1]+root.height - self.font_size
|
pos: root.right_edge - self.width-1, root.pos[1]+root.height - self.font_size - 1
|
||||||
text: 'B+' + str(int(root.y_scale))
|
text: 'B+{}'.format(root.score_scale)
|
||||||
|
opacity: int(root.show_score)
|
||||||
GraphMarkerLabel:
|
GraphMarkerLabel:
|
||||||
font_size: 0.1 * root.height
|
font_size: root.marker_font_size
|
||||||
|
color: SCORE_COLOR
|
||||||
pos: root.right_edge - self.width-1, root.mid - self.height/2 + 2
|
pos: root.right_edge - self.width-1, root.mid - self.height/2 + 2
|
||||||
text: 'Jigo'
|
text: 'Jigo'
|
||||||
|
opacity: int(root.show_score)
|
||||||
GraphMarkerLabel:
|
GraphMarkerLabel:
|
||||||
font_size: 0.1 * root.height
|
font_size: root.marker_font_size
|
||||||
|
color: SCORE_COLOR
|
||||||
pos: root.right_edge - self.width-1, root.pos[1]
|
pos: root.right_edge - self.width-1, root.pos[1]
|
||||||
text: 'W+' + str(int(root.y_scale))
|
text: 'W+' + str(int(root.score_scale))
|
||||||
|
opacity: int(root.show_score)
|
||||||
|
# wr ticks
|
||||||
|
GraphMarkerLabel:
|
||||||
|
font_size: root.marker_font_size
|
||||||
|
color: WINRATE_COLOR
|
||||||
|
pos: root.pos[0]+1, root.pos[1]+root.height - self.font_size - 1
|
||||||
|
text: "{}%".format(50 + root.winrate_scale)
|
||||||
|
opacity: int(root.show_winrate)
|
||||||
|
GraphMarkerLabel:
|
||||||
|
font_size: root.marker_font_size
|
||||||
|
color: WINRATE_COLOR
|
||||||
|
pos:root.pos[0]+1, root.pos[1]
|
||||||
|
text: "{}%".format(50 - root.winrate_scale)
|
||||||
|
opacity: int(root.show_winrate)
|
||||||
|
|
||||||
|
|
||||||
<StatsBox@BoxLayout+BackgroundColor>
|
<StatsBox@BoxLayout+BackgroundColor>
|
||||||
orientation: 'vertical'
|
orientation: 'vertical'
|
||||||
background_color: BOX_BACKGROUND_COLOR
|
background_color: BOX_BACKGROUND_COLOR
|
||||||
score: score
|
score: score
|
||||||
win_rate: win_rate
|
winrate: winrate
|
||||||
score_change: score_change
|
score_change: score_change
|
||||||
CensorableLabel:
|
CensorableLabel:
|
||||||
id: win_rate
|
id: winrate
|
||||||
label: 'Win rate'
|
label: 'Win rate'
|
||||||
text: ''
|
text: ''
|
||||||
color: WINRATE_COLOR
|
color: WINRATE_COLOR
|
||||||
@@ -625,15 +582,15 @@
|
|||||||
on_ref_press: root.dispatch('on_ref_press',args[1])
|
on_ref_press: root.dispatch('on_ref_press',args[1])
|
||||||
|
|
||||||
|
|
||||||
#:set PLAYER_BOX_HEIGHT 0.15
|
#:set player_box_height 0.15
|
||||||
#:set TIMER_BOX_HEIGHT 0.3
|
#:set timer_box_height 0.3
|
||||||
#:set GRAPH_BOX_HEIGHT 0.37
|
#:set graph_box_height 0.37
|
||||||
#:set STATS_BOX_HEIGHT 0.27
|
#:set STATS_BOX_HEIGHT 0.27
|
||||||
#:set INFO_BOX_HEIGHT 1
|
#:set INFO_BOX_HEIGHT 1
|
||||||
|
|
||||||
#:set CP_SPACING 6
|
#:set CP_SPACING 6
|
||||||
#:set CP_SMALL_SPACING 3
|
#:set CP_SMALL_SPACING 3
|
||||||
#:set CP_PADDING 4
|
#:set CP_PADDING 6
|
||||||
|
|
||||||
<ControlsPanel>:
|
<ControlsPanel>:
|
||||||
katrain: app.gui
|
katrain: app.gui
|
||||||
@@ -648,9 +605,14 @@
|
|||||||
status: status
|
status: status
|
||||||
padding: CP_PADDING
|
padding: CP_PADDING
|
||||||
spacing: CP_SPACING
|
spacing: CP_SPACING
|
||||||
tab_option_height: 20
|
player_box_height: max(50, 0.1 * root.height)
|
||||||
|
timer_box_height: max(50, 0.125 * root.height)
|
||||||
|
graph_box_height: max(100, 0.2 * root.height)
|
||||||
|
stats_box_height: max(50, 0.125 * root.height)
|
||||||
|
tab_option_height: max(15,root.height / 30)
|
||||||
BoxLayout: # -- Players
|
BoxLayout: # -- Players
|
||||||
size_hint_y: PLAYER_BOX_HEIGHT
|
size_hint_y: None
|
||||||
|
height: root.player_box_height
|
||||||
PlayerInfo:
|
PlayerInfo:
|
||||||
id: B_player
|
id: B_player
|
||||||
player: 'Black'
|
player: 'Black'
|
||||||
@@ -658,7 +620,8 @@
|
|||||||
id: W_player
|
id: W_player
|
||||||
player: 'White'
|
player: 'White'
|
||||||
BoxLayout:
|
BoxLayout:
|
||||||
size_hint_y: TIMER_BOX_HEIGHT
|
size_hint_y: None
|
||||||
|
height: root.timer_box_height
|
||||||
spacing: CP_SPACING
|
spacing: CP_SPACING
|
||||||
PonderInfo:
|
PonderInfo:
|
||||||
id: ponder
|
id: ponder
|
||||||
@@ -668,27 +631,28 @@
|
|||||||
id: timer
|
id: timer
|
||||||
size_hint_x: 0.7
|
size_hint_x: 0.7
|
||||||
CollapsablePanel:
|
CollapsablePanel:
|
||||||
size_hint_y_open: GRAPH_BOX_HEIGHT
|
height_open: root.graph_box_height
|
||||||
closed_label: 'Score Graph'
|
closed_label: 'closedlabel:scoregraph'
|
||||||
options: ['Score','Win Rate','PtLoss']
|
options: ['score','winrate','points']
|
||||||
option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR]
|
option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR]
|
||||||
option_default_active: [True,False,False]
|
option_default_active: [True,False,False]
|
||||||
options_height: root.tab_option_height
|
options_height: root.tab_option_height
|
||||||
|
on_option_state: graph.show_graphs(args[1])
|
||||||
ScoreGraph:
|
ScoreGraph:
|
||||||
id: graph
|
id: graph
|
||||||
CollapsablePanel:
|
CollapsablePanel:
|
||||||
size_hint_y_open: STATS_BOX_HEIGHT
|
height_open: root.stats_box_height
|
||||||
closed_label: 'Move Stats'
|
closed_label: 'closedlabel:movestats'
|
||||||
options: ['Score','Win Rate','PtLoss']
|
options: ['score','winrate','points']
|
||||||
option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR]
|
option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR]
|
||||||
option_default_active: [True,True,True]
|
option_default_active: [True,True,True]
|
||||||
options_height: root.tab_option_height
|
options_height: root.tab_option_height
|
||||||
StatsBox:
|
StatsBox:
|
||||||
id: stats
|
id: stats
|
||||||
CollapsablePanel:
|
CollapsablePanel:
|
||||||
size_hint_y: INFO_BOX_HEIGHT
|
size_hint_y_open: 1
|
||||||
closed_label: 'Move Info & Notes'
|
closed_label: 'closedlabel:info¬es'
|
||||||
options: ['Info','Notes']
|
options: ['info','notes']
|
||||||
option_colors: [RED,GREEN]
|
option_colors: [RED,GREEN]
|
||||||
option_default_active: [True,False]
|
option_default_active: [True,False]
|
||||||
options_height: root.tab_option_height
|
options_height: root.tab_option_height
|
||||||
@@ -711,7 +675,8 @@
|
|||||||
on_text: root.katrain.set_note(self.text)
|
on_text: root.katrain.set_note(self.text)
|
||||||
hint_text: 'Your SGF notes for this position here.'
|
hint_text: 'Your SGF notes for this position here.'
|
||||||
height: min( (len(self._lines)+0.7) * self.line_height, self.parent.height - status.height - 2.7*self.line_height)
|
height: min( (len(self._lines)+0.7) * self.line_height, self.parent.height - status.height - 2.7*self.line_height)
|
||||||
|
Label:
|
||||||
|
size_hint_y: 1e-9 # takes up remaining space if info is closed
|
||||||
|
|
||||||
<RHSButton@AutoSizedMDFlatRectangleButton>:
|
<RHSButton@AutoSizedMDFlatRectangleButton>:
|
||||||
md_bg_color: BOX_BACKGROUND_COLOR
|
md_bg_color: BOX_BACKGROUND_COLOR
|
||||||
@@ -722,7 +687,7 @@
|
|||||||
on_press: app.gui.update_state()
|
on_press: app.gui.update_state()
|
||||||
size_hint_y: 1
|
size_hint_y: 1
|
||||||
|
|
||||||
<AnalysisControls@MDBoxLayout>:
|
<AnalysisControls>:
|
||||||
katrain: app.gui
|
katrain: app.gui
|
||||||
orientation: 'horizontal'
|
orientation: 'horizontal'
|
||||||
padding: CP_PADDING, CP_PADDING
|
padding: CP_PADDING, CP_PADDING
|
||||||
@@ -732,9 +697,8 @@
|
|||||||
policy: policy
|
policy: policy
|
||||||
hints: hints
|
hints: hints
|
||||||
ownership: ownership
|
ownership: ownership
|
||||||
analyze_extra: analyze_extra
|
analysis_button: analysis_button
|
||||||
analyze_equalize: analyze_equalize
|
Label:
|
||||||
analyze_sweep: analyze_sweep
|
|
||||||
RHSToggleButton:
|
RHSToggleButton:
|
||||||
id: show_children
|
id: show_children
|
||||||
text: 'Next\nMoves'
|
text: 'Next\nMoves'
|
||||||
@@ -757,21 +721,10 @@
|
|||||||
text: 'Top\nMoves'
|
text: 'Top\nMoves'
|
||||||
color: WHITE
|
color: WHITE
|
||||||
RHSButton:
|
RHSButton:
|
||||||
id: analyze_extra
|
id: analysis_button
|
||||||
text: 'Extra'
|
on_press: root.open_analysis_menu()
|
||||||
tooltip_text: '[a]\nExtra analysis\nto increase accuracy\nof top move predictions\nand score difference'
|
text: 'Analysis'
|
||||||
on_left_press: root.katrain("analyze-extra","extra")
|
Label:
|
||||||
RHSButton:
|
|
||||||
id: analyze_equalize
|
|
||||||
text: 'Equalize'
|
|
||||||
tooltip_text: '[s]\nAnalysis of all\npredicted top moves\nwith the same accuracy'
|
|
||||||
on_left_press: root.katrain("analyze-extra","equalize")
|
|
||||||
RHSButton:
|
|
||||||
id: analyze_sweep
|
|
||||||
text: 'Sweep'
|
|
||||||
tooltip_text: '[d]\nFast analysis\nof all legal moves'
|
|
||||||
on_left_press: root.katrain("analyze-extra","sweep")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<MainMenuItem>
|
<MainMenuItem>
|
||||||
@@ -884,18 +837,26 @@
|
|||||||
AnalysisControls:
|
AnalysisControls:
|
||||||
id: analysis_controls
|
id: analysis_controls
|
||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
height: min(100,self.width / 13.5) if not root.zen else 1
|
height: min(100,self.width / 13.5) if not root.zen else 0
|
||||||
|
opacity: 0 if root.zen else 1
|
||||||
BadukPanWidget:
|
BadukPanWidget:
|
||||||
id: board_gui
|
id: board_gui
|
||||||
BadukPanControls:
|
BadukPanControls:
|
||||||
id: board_controls
|
id: board_controls
|
||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
height: min(100,self.width / 13.5)
|
height: min(100,self.width / 13.5)
|
||||||
ControlsPanel:
|
MDBoxLayout:
|
||||||
id: controls
|
|
||||||
size_hint_x: None
|
size_hint_x: None
|
||||||
width: 0 if root.zen else self.height * 0.35
|
width: 0 if root.zen else self.height * 0.4
|
||||||
opacity: 0 if root.zen else 1
|
opacity: 0 if root.zen else 1
|
||||||
|
orientation: 'vertical'
|
||||||
|
MDBoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
height: analysis_controls.height
|
||||||
|
Label:
|
||||||
|
text: 'BlaBla'
|
||||||
|
ControlsPanel:
|
||||||
|
id: controls
|
||||||
MyNavigationDrawer:
|
MyNavigationDrawer:
|
||||||
id: nav_drawer
|
id: nav_drawer
|
||||||
state: "close"
|
state: "close"
|
||||||
|
|||||||
@@ -401,17 +401,18 @@ class BadukPanWidget(Widget):
|
|||||||
def show_pv_from_comments(self, pv_str):
|
def show_pv_from_comments(self, pv_str):
|
||||||
self.set_animating_pv(pv_str[1:].split(" "), self.katrain.controls.active_comment_node.parent)
|
self.set_animating_pv(pv_str[1:].split(" "), self.katrain.controls.active_comment_node.parent)
|
||||||
|
|
||||||
|
class AnalysisControls(MDBoxLayout):
|
||||||
class BadukPanControls(MDFloatLayout):
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.analysis_menu = None
|
self.analysis_menu=None
|
||||||
Clock.schedule_once(self.init_menus, 1)
|
Clock.schedule_once(self.build_menu,0)
|
||||||
|
|
||||||
def init_menus(self, _dt):
|
def build_menu(self,_dt):
|
||||||
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
|
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
|
||||||
self.analysis_menu = MDDropdownMenu(caller=self.analysis_button, items=menu_items, width_mult=4)
|
self.analysis_menu = MDDropdownMenu(caller=self.analysis_button, items=menu_items, width_mult=4)
|
||||||
|
|
||||||
def open_analysis_menu(self):
|
def open_analysis_menu(self):
|
||||||
if self.analysis_menu:
|
self.analysis_menu.open()
|
||||||
self.analysis_menu.open()
|
|
||||||
|
class BadukPanControls(MDFloatLayout):
|
||||||
|
pass
|
||||||
@@ -84,7 +84,7 @@ class ControlsPanel(BoxLayout):
|
|||||||
|
|
||||||
if current_node.analysis_ready:
|
if current_node.analysis_ready:
|
||||||
self.stats.score.text = current_node.format_score()
|
self.stats.score.text = current_node.format_score()
|
||||||
self.stats.win_rate.text = current_node.format_win_rate()
|
self.stats.winrate.text = current_node.format_winrate()
|
||||||
if move and last_player_was_human_or_both_robots: # don't immediately hide this when an ai moves comes in
|
if move and last_player_was_human_or_both_robots: # don't immediately hide this when an ai moves comes in
|
||||||
points_lost = current_node.points_lost
|
points_lost = current_node.points_lost
|
||||||
self.stats.score_change.label = f"Points lost" if points_lost and points_lost > 0 else f"Points gained"
|
self.stats.score_change.label = f"Points lost" if points_lost and points_lost > 0 else f"Points gained"
|
||||||
@@ -98,7 +98,7 @@ class ControlsPanel(BoxLayout):
|
|||||||
self.stats.score_change.text = f"{current_node.parent.move.player}: {abs(points_lost):.1f}" if points_lost else "-"
|
self.stats.score_change.text = f"{current_node.parent.move.player}: {abs(points_lost):.1f}" if points_lost else "-"
|
||||||
elif both_players_are_robots and current_node.parent and current_node.parent.analysis_ready:
|
elif both_players_are_robots and current_node.parent and current_node.parent.analysis_ready:
|
||||||
self.stats.score.text = current_node.parent.format_score()
|
self.stats.score.text = current_node.parent.format_score()
|
||||||
self.stats.win_rate.text = current_node.parent.format_win_rate()
|
self.stats.winrate.text = current_node.parent.format_winrate()
|
||||||
|
|
||||||
self.graph.update_value(current_node)
|
self.graph.update_value(current_node)
|
||||||
self.note.text = current_node.note
|
self.note.text = current_node.note
|
||||||
|
|||||||
+35
-13
@@ -1,19 +1,26 @@
|
|||||||
import math
|
import math
|
||||||
|
|
||||||
from kivy.properties import ListProperty, NumericProperty
|
from kivy.properties import ListProperty, NumericProperty, BooleanProperty
|
||||||
|
|
||||||
from katrain.gui.kivyutils import BackgroundColor
|
from katrain.gui.kivyutils import BackgroundColor
|
||||||
|
|
||||||
|
|
||||||
class ScoreGraph(BackgroundColor):
|
class ScoreGraph(BackgroundColor):
|
||||||
|
show_score = BooleanProperty(True)
|
||||||
|
show_winrate = BooleanProperty(True)
|
||||||
|
show_pointloss = BooleanProperty(True)
|
||||||
|
|
||||||
nodes = ListProperty([])
|
nodes = ListProperty([])
|
||||||
score_points = ListProperty([])
|
score_points = ListProperty([])
|
||||||
winrate_points = ListProperty([])
|
winrate_points = ListProperty([])
|
||||||
|
|
||||||
dot_pos = ListProperty([0, 0])
|
dot_pos = ListProperty([0, 0])
|
||||||
highlighted_index = NumericProperty(None)
|
highlighted_index = NumericProperty(None)
|
||||||
y_scale = NumericProperty(5)
|
|
||||||
highlight_size = NumericProperty(5)
|
highlight_size = NumericProperty(5)
|
||||||
|
|
||||||
|
score_scale = NumericProperty(5)
|
||||||
|
winrate_scale = NumericProperty(5)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.bind(pos=self.update_graph, size=self.update_graph)
|
self.bind(pos=self.update_graph, size=self.update_graph)
|
||||||
@@ -26,26 +33,41 @@ class ScoreGraph(BackgroundColor):
|
|||||||
self.nodes.append(node)
|
self.nodes.append(node)
|
||||||
self.highlighted_index = 0
|
self.highlighted_index = 0
|
||||||
|
|
||||||
|
def show_graphs(self,keys):
|
||||||
|
self.show_score = keys['score']
|
||||||
|
self.show_winrate = keys['winrate']
|
||||||
|
self.show_pointloss = keys['points']
|
||||||
|
|
||||||
def update_graph(self, *args):
|
def update_graph(self, *args):
|
||||||
nodes = self.nodes
|
nodes = self.nodes
|
||||||
if nodes:
|
if nodes:
|
||||||
values = [n.score if n and n.score else math.nan for n in nodes]
|
score_values = [n.score if n and n.score else math.nan for n in nodes]
|
||||||
nn_values = [n.score for n in nodes if n and n.score]
|
score_nn_values = [n.score for n in nodes if n and n.score]
|
||||||
val_range = min(nn_values or [0]), max(nn_values or [0])
|
score_values_range = min(score_nn_values or [0]), max(score_nn_values or [0])
|
||||||
|
|
||||||
self.y_scale = math.ceil(max(5, max(-val_range[0], val_range[1])) / 5) * 5
|
winrate_values = [(n.winrate-0.5)*100 if n and n.winrate else math.nan for n in nodes]
|
||||||
|
winrate_nn_values = [(n.winrate-0.5)*100 for n in nodes if n and n.winrate]
|
||||||
|
winrate_values_range = min(winrate_nn_values or [0]), max(winrate_nn_values or [0])
|
||||||
|
|
||||||
xscale = self.width / max(len(values) - 1, 15)
|
score_granularity = 5
|
||||||
|
winrate_granularity = 10
|
||||||
|
self.score_scale = max(math.ceil( max(-score_values_range[0], score_values_range[1]) / score_granularity),1) * score_granularity
|
||||||
|
self.winrate_scale = max(math.ceil(max(-winrate_values_range[0], winrate_values_range[1]) / winrate_granularity), 1) * winrate_granularity
|
||||||
|
|
||||||
|
print(self.score_scale,score_values_range,score_values)
|
||||||
|
|
||||||
|
xscale = self.width / max(len(score_values) - 1, 15)
|
||||||
available_height = self.height
|
available_height = self.height
|
||||||
line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.y_scale)] for i, val in enumerate(values)]
|
score_line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.score_scale)] for i, val in enumerate(score_values)]
|
||||||
self.score_points = sum(line_points, [])
|
winrate_line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.winrate_scale)] for i, val in enumerate(winrate_values)]
|
||||||
self.winrate_points = self.score_points # TODO
|
self.score_points = sum(score_line_points, [])
|
||||||
|
self.winrate_points = sum(winrate_line_points,[])
|
||||||
|
|
||||||
if self.highlighted_index is not None:
|
if self.highlighted_index is not None:
|
||||||
self.highlighted_index = min(self.highlighted_index, len(values) - 1)
|
self.highlighted_index = min(self.highlighted_index, len(score_values) - 1)
|
||||||
dot_point = line_points[self.highlighted_index]
|
dot_point = score_line_points[self.highlighted_index]
|
||||||
if math.isnan(dot_point[1]):
|
if math.isnan(dot_point[1]):
|
||||||
dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((nn_values or [0])[-1] / self.y_scale)
|
dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((score_nn_values or [0])[-1] / self.score_scale)
|
||||||
self.dot_pos = [c - self.highlight_size / 2 for c in dot_point]
|
self.dot_pos = [c - self.highlight_size / 2 for c in dot_point]
|
||||||
|
|
||||||
def update_value(self, node):
|
def update_value(self, node):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from kivy.uix.widget import Widget
|
|||||||
|
|
||||||
# --new
|
# --new
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import RectangularRippleBehavior
|
from kivymd.uix.behaviors import RectangularRippleBehavior, CircularRippleBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.button import BasePressedButton, BaseFlatButton
|
from kivymd.uix.button import BasePressedButton, BaseFlatButton
|
||||||
from kivymd.uix.floatlayout import MDFloatLayout
|
from kivymd.uix.floatlayout import MDFloatLayout
|
||||||
@@ -98,7 +98,7 @@ class AutoSizedMDFlatRectangleToggleButton(SizedMDFlatRectangleToggleButton):
|
|||||||
hor_padding = NumericProperty(3)
|
hor_padding = NumericProperty(3)
|
||||||
|
|
||||||
|
|
||||||
class TransparentIconButton(Button):
|
class TransparentIconButton(CircularRippleBehavior,Button):
|
||||||
icon_size = ListProperty([25, 25])
|
icon_size = ListProperty([25, 25])
|
||||||
icon = StringProperty("")
|
icon = StringProperty("")
|
||||||
|
|
||||||
@@ -179,9 +179,9 @@ class CollapsablePanel(MDBoxLayout):
|
|||||||
|
|
||||||
def build_options(self, *args, **kwargs):
|
def build_options(self, *args, **kwargs):
|
||||||
self.header = MDBoxLayout(height=self.options_height,size_hint_y=None,
|
self.header = MDBoxLayout(height=self.options_height,size_hint_y=None,
|
||||||
padding=[self.options_left_padding, 0, 0, 0], spacing=2)
|
padding=[self.options_left_padding, 0, 0, 0], spacing=3)
|
||||||
self.option_buttons = []
|
self.option_buttons = []
|
||||||
option_labels = self.option_labels or [i18n._(opt) for opt in self.options]
|
option_labels = self.option_labels or [i18n._(f"tab:{opt}") for opt in self.options]
|
||||||
for lbl, opt_col, active in zip(option_labels, self.option_colors, self.option_default_active):
|
for lbl, opt_col, active in zip(option_labels, self.option_colors, self.option_default_active):
|
||||||
button = AutoSizedMDFlatRectangleToggleButton(text=lbl,color=opt_col, height=self.options_height,
|
button = AutoSizedMDFlatRectangleToggleButton(text=lbl,color=opt_col, height=self.options_height,
|
||||||
on_press=self.trigger_select, state="down" if active else "normal")
|
on_press=self.trigger_select, state="down" if active else "normal")
|
||||||
@@ -228,7 +228,6 @@ class CollapsablePanel(MDBoxLayout):
|
|||||||
self.build()
|
self.build()
|
||||||
|
|
||||||
def set_state(self, state="toggle"):
|
def set_state(self, state="toggle"):
|
||||||
print("SS",state)
|
|
||||||
if state == "toggle":
|
if state == "toggle":
|
||||||
state = "close" if self.state == "open" else "open"
|
state = "close" if self.state == "open" else "open"
|
||||||
self.state = state
|
self.state = state
|
||||||
@@ -238,7 +237,7 @@ class CollapsablePanel(MDBoxLayout):
|
|||||||
|
|
||||||
def trigger_select(self, *_args):
|
def trigger_select(self, *_args):
|
||||||
if self.state == "open":
|
if self.state == "open":
|
||||||
self.on_option_state({opt:btn.state == "down" for opt,btn in zip(self.options,self.option_buttons)})
|
self.dispatch("on_option_state",{opt:btn.state == "down" for opt,btn in zip(self.options,self.option_buttons)})
|
||||||
|
|
||||||
def on_option_state(self, options):
|
def on_option_state(self, options):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Binary file not shown.
@@ -22,6 +22,31 @@ msgid "pass-button-text"
|
|||||||
msgstr "Pass"
|
msgstr "Pass"
|
||||||
|
|
||||||
msgid "pass-button-tooltip"
|
msgid "pass-button-tooltip"
|
||||||
msgstr "[space]\nPass"
|
msgstr ""
|
||||||
|
"[space]\n"
|
||||||
|
"Pass"
|
||||||
|
|
||||||
|
msgid "tab:score"
|
||||||
|
msgstr "Score"
|
||||||
|
|
||||||
|
msgid "tab:winrate"
|
||||||
|
msgstr "Win Rate"
|
||||||
|
|
||||||
|
msgid "tab:points"
|
||||||
|
msgstr "Point Loss"
|
||||||
|
|
||||||
|
msgid "tab:info"
|
||||||
|
msgstr "Info"
|
||||||
|
|
||||||
|
msgid "tab:notes"
|
||||||
|
msgstr "Notes"
|
||||||
|
|
||||||
|
msgid 'closedlabel:scoregraph'
|
||||||
|
msgstr 'Score Graph'
|
||||||
|
|
||||||
|
|
||||||
|
msgid 'closedlabel:movestats'
|
||||||
|
msgstr 'Move Stats'
|
||||||
|
|
||||||
|
msgid 'closedlabel:info¬es'
|
||||||
|
msgstr 'Move Info & Notes'
|
||||||
Binary file not shown.
@@ -0,0 +1,59 @@
|
|||||||
|
# KaTrain i18n file
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Language: Nederlands\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
msgid "Hello World"
|
||||||
|
msgstr "안녕하세요 여러분"
|
||||||
|
|
||||||
|
msgid "English"
|
||||||
|
msgstr "영어"
|
||||||
|
|
||||||
|
msgid "Dutch"
|
||||||
|
msgstr "네덜란드어"
|
||||||
|
|
||||||
|
msgid "pass-button-text"
|
||||||
|
msgstr "페스"
|
||||||
|
|
||||||
|
msgid "pass-button-tooltip"
|
||||||
|
msgstr ""
|
||||||
|
"[스페이스 바]\n"
|
||||||
|
"페스"
|
||||||
|
|
||||||
|
msgid "KataGo"
|
||||||
|
msgstr "카타고"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:winrate"
|
||||||
|
msgstr "Win Rate"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:info"
|
||||||
|
msgstr "Info"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:points"
|
||||||
|
msgstr "Point Loss"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:notes"
|
||||||
|
msgstr "Notes"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:scoregraph"
|
||||||
|
msgstr "Score Graph"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:movestats"
|
||||||
|
msgstr "Move Stats"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:score"
|
||||||
|
msgstr "Score"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:info¬es"
|
||||||
|
msgstr "Move Info & Notes"
|
||||||
Binary file not shown.
@@ -19,5 +19,42 @@ msgid "pass-button-text"
|
|||||||
msgstr "Pas"
|
msgstr "Pas"
|
||||||
|
|
||||||
msgid "pass-button-tooltip"
|
msgid "pass-button-tooltip"
|
||||||
msgstr "[spatiebalk]\nPas"
|
msgstr ""
|
||||||
|
"[spatiebalk]\n"
|
||||||
|
"Pas"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "KataGo"
|
||||||
|
msgstr "KataGo"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:winrate"
|
||||||
|
msgstr "Win Rate"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:points"
|
||||||
|
msgstr "Point Loss"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:score"
|
||||||
|
msgstr "Score"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:notes"
|
||||||
|
msgstr "Notes"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "tab:info"
|
||||||
|
msgstr "Info"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:scoregraph"
|
||||||
|
msgstr "Score Graph"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:info¬es"
|
||||||
|
msgstr "Move Info & Notes"
|
||||||
|
|
||||||
|
#. TODO
|
||||||
|
msgid "closedlabel:movestats"
|
||||||
|
msgstr "Move Stats"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Reference in new issue
Block a user