beter graph and i18n

This commit is contained in:
Sander Land committed 2020-05-24 20:45:11 +02:00
1 parent 738578ee5a
commit c424541b35
15 files changed
+330 -179

No files matched your search

+40
View File
@@ -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
View File
@@ -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),
+14 -7
View File
@@ -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
View File
@@ -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&notes'
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"
+8 -7
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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):
+5 -6
View File
@@ -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.
+26 -1
View File
@@ -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&notes'
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&notes"
msgstr "Move Info & Notes"
Binary file not shown.
+38 -1
View File
@@ -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&notes"
msgstr "Move Info & Notes"
#. TODO
msgid "closedlabel:movestats"
msgstr "Move Stats"
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB