This commit is contained in:
Sander Land committed 2020-06-21 00:00:27 +02:00
1 parent 94c5362a01
commit 71b1dc2d70
5 files changed
+193 -20

No files matched your search

+2 -2
View File
@@ -65,7 +65,7 @@ from katrain.core.engine import KataGoEngine
from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
from katrain.core.sgf_parser import Move, ParseError
from katrain.gui.kivyutils import *
from katrain.gui.popups import ConfigPopup, LoadSGFPopup, NewGamePopup, AIPopup
from katrain.gui.popups import ConfigPopup, LoadSGFPopup, NewGamePopup, ConfigAIPopup
from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL, LIGHTGREY
from katrain.gui.widgets.graph import ScoreGraph
from katrain.gui.widgets.movetree import MoveTree
@@ -311,7 +311,7 @@ class KaTrainGui(Screen, KaTrainBase):
self.controls.timer.paused = True
if not self.ai_settings_popup:
self.ai_settings_popup = I18NPopup(
title_key="ai settings", size=[dp(600), dp(600)], content=AIPopup(self)
title_key="ai settings", size=[dp(600), dp(600)], content=ConfigAIPopup(self)
).__self__
self.ai_settings_popup.content.popup = self.ai_settings_popup
self.ai_settings_popup.open()
+13 -9
View File
@@ -1,6 +1,12 @@
VERSION = "1.2.1"
VERSION = "1.3.0"
HOMEPAGE = "https://github.com/sanderland/katrain"
CONFIG_MIN_VERSION = "1.2.0"
CONFIG_MIN_VERSION = "1.2.0" # keep config files from this version
OUTPUT_ERROR = -1
OUTPUT_KATAGO_STDERR = -0.5
OUTPUT_INFO = 0
OUTPUT_DEBUG = 1
OUTPUT_EXTRA_DEBUG = 2
PLAYER_HUMAN, PLAYER_AI = "player:human", "player:ai"
PLAYER_TYPES = [PLAYER_HUMAN, PLAYER_AI]
@@ -43,7 +49,7 @@ AI_STRATEGIES_RECOMMENDED_ORDER = [
]
AI_STRENGTH = {
AI_STRENGTH = { # not used
AI_DEFAULT: "9d",
AI_POLICY: "4d",
AI_JIGO: "?d",
@@ -57,9 +63,7 @@ AI_STRENGTH = {
AI_RANK: "15k - 3d",
}
OUTPUT_ERROR = -1
OUTPUT_KATAGO_STDERR = -0.5
OUTPUT_INFO = 0
OUTPUT_DEBUG = 1
OUTPUT_EXTRA_DEBUG = 2
AI_OPTION_VALUES = {
"kyu_rank": [(k, f"{k}[strength:kyu]") for k in range(15, 0, -1)]
+ [(k, f"{1-k}[strength:dan]") for k in range(0, -3, -1)]
}
+33 -8
View File
@@ -4,7 +4,7 @@ import re
from typing import Any, Dict, List, Tuple, Union
from kivy.clock import Clock
from kivy.properties import BooleanProperty, NumericProperty, StringProperty
from kivy.properties import BooleanProperty, NumericProperty, StringProperty, ListProperty
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
@@ -21,12 +21,14 @@ from katrain.core.constants import (
OUTPUT_DEBUG,
OUTPUT_ERROR,
OUTPUT_INFO,
AI_OPTION_VALUES,
)
from katrain.core.engine import KataGoEngine
from katrain.core.lang import i18n
from katrain.core.utils import find_package_resource
from katrain.gui.kivyutils import BackgroundMixin, I18NSpinner
from katrain.gui.style import DEFAULT_FONT, EVAL_COLORS
from katrain.gui.widgets.selection_slider import SelectionSlider
class I18NPopup(Popup):
@@ -129,6 +131,21 @@ class LabelledIntInput(LabelledTextInput):
return int(self.text or "0")
class LabelledSelectionSlider(BoxLayout):
input_property = StringProperty("")
values = ListProperty([(0, "")]) # (value:numeric,label:string) pairs
def set_value(self, v):
self.slider.set_value(v)
self.textbox.text = str(v)
@property
def input_value(self):
if self.textbox.text:
return float(self.textbox.text)
return self.slider.values[self.silder.index][0]
class InputParseError(Exception):
pass
@@ -183,12 +200,14 @@ class QuickConfigGui(MDBoxLayout):
return self._set_properties_subtree(self)
def _set_properties_subtree(self, widget):
if isinstance(widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox)) and getattr(
widget, "input_property", None
):
if isinstance(
widget, (LabelledTextInput, LabelledSpinner, LabelledCheckBox, LabelledSelectionSlider)
) and getattr(widget, "input_property", None):
value = self.get_setting(widget.input_property)[0]
if isinstance(widget, LabelledCheckBox):
widget.active = value is True
elif isinstance(widget, LabelledSelectionSlider):
widget.set_value(value)
elif isinstance(widget, LabelledSpinner):
selected = 0
try:
@@ -281,7 +300,7 @@ class DescriptionLabel(Label):
pass
class AIPopup(QuickConfigGui):
class ConfigAIPopup(QuickConfigGui):
max_options = NumericProperty(6)
def __init__(self, katrain):
@@ -300,9 +319,15 @@ class AIPopup(QuickConfigGui):
self.help_label.text = i18n._(strategy.replace("ai:", "aihelp:"))
for k, v in sorted(mode_settings.items(), key=lambda kv: kv[0]):
self.options_grid.add_widget(DescriptionLabel(text=k))
self.options_grid.add_widget(
wrap_anchor(LabelledFloatInput(text=str(v), input_property=f"ai/{strategy}/{k}"))
)
if k in AI_OPTION_VALUES:
values = [(v, re.sub(r"\[(.*?)\]", lambda m: i18n._(m[1]), l)) for v, l in AI_OPTION_VALUES[k]]
widget = LabelledSelectionSlider(values=values, input_property=f"ai/{strategy}/{k}")
widget.set_value(v)
self.options_grid.add_widget(wrap_anchor(widget))
else:
self.options_grid.add_widget(
wrap_anchor(LabelledFloatInput(text=str(v), input_property=f"ai/{strategy}/{k}"))
)
for _ in range((self.max_options - len(mode_settings)) * 2):
self.options_grid.add_widget(Label())
+132
View File
@@ -0,0 +1,132 @@
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.properties import (
NumericProperty,
AliasProperty,
ListProperty,
BooleanProperty,
)
from kivymd.uix.label import MDLabel
from kivymd.uix.selectioncontrol import Thumb
from katrain.gui.style import LIGHTER_BACKGROUND_COLOR
class SelectionSlider(Widget):
__events__ = ["on_select"]
active = BooleanProperty(False)
hint = BooleanProperty(True)
index = NumericProperty(0) # selected index
values = ListProperty([(0, "")]) # (value:numeric,label:string) pairs
normalized_pos = NumericProperty(0) # slider relative pos from 0-1
px_pos = NumericProperty(0) # actual px pos
padding = NumericProperty("16sp")
track_color = ListProperty([1, 1, 1, 0.3])
thumb_color = LIGHTER_BACKGROUND_COLOR
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.bind(size=self.set_index_and_positions,pos=self.set_index_and_positions,values=self.set_index_and_positions,index=self.set_index_and_positions)
def set_index_and_positions(self, *_args):
self.index = max(0, min(self.index, len(self.values) - 1))
self.normalized_pos = self.index / (len(self.values)-1)
self.px_pos = self.x + self.padding + self.normalized_pos * (self.width - 2 * self.padding)
@property
def value(self):
return self.values[self.index][0]
def set_value(self, set_value): # set to closest value
eq_value = sorted([(abs(v - set_value), i) for i, (v, l) in enumerate(self.values)])
self.index = eq_value[0][1]
def set_from_pos(self,pos):
norm_value = (pos[0] - self.x - self.padding) / (self.width - 2 * self.padding)
self.index = round(norm_value * (len(self.values) - 1))
def on_touch_down(self, touch):
if self.disabled or not self.collide_point(*touch.pos):
return
if touch.is_mouse_scrolling:
if "down" in touch.button or "left" in touch.button:
self.index += 1
if "up" in touch.button or "right" in touch.button:
self.index -= 1
else:
touch.grab(self)
self.active = True
self.set_from_pos(touch.pos)
return True
def on_touch_move(self, touch):
if touch.grab_current == self:
self.set_from_pos(touch.pos)
return True
def on_touch_up(self, touch):
if touch.grab_current == self:
self.set_from_pos(touch.pos)
self.active = False
self.dispatch("on_select", self.value)
return True
def on_select(self,value):
pass
KV = """
<SelectionSlider>:
id: slider
canvas:
Clear
Color:
rgba:
self.track_color
Rectangle:
size:
(self.width - self.padding*2, dp(4))
pos:
(self.x + self.padding, self.center_y - dp(4))
Color:
rgba:
self.thumb_color
Rectangle:
size:
((self.width-self.padding*2)*self.normalized_pos, sp(4))
pos:
(self.x + self.padding, self.center_y - dp(4))
Thumb:
id: thumb
size_hint: None, None
size:
((dp(24), dp(24)) if root.active else (dp(16), dp(16)))
pos:
(slider.px_pos - dp(8), slider.center_y - thumb.height/2 - dp(2))
color:
root.thumb_color
elevation:
4 if root.active else 2
MDCard:
id: hint_box
size_hint: None, None
md_bg_color: [1, 1, 1, 1] if root.active else [0, 0, 0, 0]
elevation: 4 if root.active else 0
size:
(dp(28), dp(28) if root.active else (dp(20), dp(20)))
pos:
(slider.px_pos - dp(9), slider.center_y - hint_box.height / 2 + dp(30))
MDLabel:
text: slider.values[slider.index][1]
font_style: "Caption"
halign: "center"
color: root.thumb_color if root.active else [0, 0, 0, 0]
"""
Builder.load_string(KV)
+13 -1
View File
@@ -366,8 +366,20 @@
on_press: root.update_config(True)
<LabelledSelectionSlider>:
slider: slider
textbox: textbox
SelectionSlider:
id: slider
size_hint: 3,1
values: root.values
on_select: textbox.text = str(slider.value)
LabelledFloatInput:
id: textbox
<AIPopup>
<ConfigAIPopup>:
options_grid: options_grid
help_label: help_label
ai_select: ai_select