hints for player names, flake8, rankgraph ded

This commit is contained in:
Sander Land committed 2020-12-09 22:15:14 +01:00
1 parent 0276e4b2a4
commit 2499488a20
35 files changed
+96 -227

No files matched your search

+2 -2
View File
@@ -27,7 +27,7 @@ for lang in locales:
pofile[lang] = os.path.join(localedir, lang, "LC_MESSAGES", "katrain.po")
po[lang] = polib.pofile(pofile[lang])
for entry in po[lang].translated_entries():
if "TODO" in entry.comment and not "DEPRECATED" in entry.comment:
if "TODO" in entry.comment and "DEPRECATED" not in entry.comment:
todos[lang].append(entry)
strings_to_langs[entry.msgid][lang] = entry
strings_to_keys[entry.msgid][lang] = set(re.findall("{.*?}", entry.msgstr))
@@ -75,7 +75,7 @@ for lang in locales:
for msgid, lang_entries in strings_to_langs.items():
if lang in lang_entries and "TODO" in lang_entries[lang].comment:
if any(e.msgstr == lang_entries[lang].msgstr for l, e in lang_entries.items() if l != lang):
if any(e.msgstr == lang_entries[lang].msgstr for ll, e in lang_entries.items() if ll != lang):
todo_comment = (
f"TODO - {lang_entries[DEFAULT_LANG].comment}" if lang_entries[DEFAULT_LANG].comment else "TODO"
) # update todo
+5 -5
View File
@@ -74,7 +74,7 @@ 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, ConfigAIPopup
from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL, LIGHTGREY
from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL
from katrain.gui.widgets import *
from katrain.gui.badukpan import AnalysisControls, BadukPanControls, BadukPanWidget
from katrain.gui.controlspanel import ControlsPanel
@@ -108,14 +108,14 @@ class KaTrainGui(Screen, KaTrainBase):
super().log(message, level)
if level == OUTPUT_KATAGO_STDERR and "ERROR" not in self.controls.status.text:
if "starting" in message.lower():
self.controls.set_status(f"KataGo engine starting...", STATUS_INFO)
self.controls.set_status("KataGo engine starting...", STATUS_INFO)
if message.startswith("Tuning"):
self.controls.set_status(
f"KataGo is tuning settings for first startup, please wait." + message, STATUS_INFO
"KataGo is tuning settings for first startup, please wait." + message, STATUS_INFO
)
return
if "ready" in message.lower():
self.controls.set_status(f"KataGo engine ready.", STATUS_INFO)
self.controls.set_status("KataGo engine ready.", STATUS_INFO)
if (
level == OUTPUT_ERROR
or (level == OUTPUT_KATAGO_STDERR and "error" in message.lower() and "tuning" not in message.lower())
@@ -450,7 +450,7 @@ class KaTrainGui(Screen, KaTrainBase):
def load_sgf_from_clipboard(self):
clipboard = Clipboard.paste()
if not clipboard:
self.controls.set_status(f"Ctrl-V pressed but clipboard is empty.", STATUS_INFO)
self.controls.set_status("Ctrl-V pressed but clipboard is empty.", STATUS_INFO)
return
url_match = re.match(r"(?P<url>https?://[^\s]+)", clipboard)
+3 -3
View File
@@ -203,7 +203,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
game, cn, {"playoutDoublingAdvantage": pda, "playoutDoublingAdvantagePla": "BLACK"}
)
if not handicap_analysis:
game.katrain.log(f"Error getting handicap-based move", OUTPUT_ERROR)
game.katrain.log("Error getting handicap-based move", OUTPUT_ERROR)
ai_mode = AI_DEFAULT
while not cn.analysis_complete:
@@ -225,7 +225,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
ai_mode in [AI_LOCAL, AI_TENUKI] and not (cn.move and cn.move.coords)
):
ai_mode = AI_WEIGHTED
ai_thoughts += f"Strategy override, using policy-weighted strategy instead. "
ai_thoughts += "Strategy override, using policy-weighted strategy instead. "
ai_settings = {"pick_override": 0.9, "weaken_fac": 1, "lower_bound": 0.02}
if top_5_pass:
@@ -336,7 +336,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
AI_HANDICAP,
]: # don't play suicidal to balance score
aimove = top_cand
ai_thoughts += f"Top move is pass, so passing regardless of strategy. "
ai_thoughts += "Top move is pass, so passing regardless of strategy. "
else:
if ai_mode == AI_JIGO:
sign = cn.player_sign(cn.next_player)
-1
View File
@@ -10,7 +10,6 @@ from kivy.clock import Clock
from katrain.core.constants import (
ANALYSIS_FORMAT_VERSION,
HOMEPAGE,
OUTPUT_DEBUG,
OUTPUT_INFO,
PLAYER_AI,
+2 -2
View File
@@ -280,7 +280,7 @@ class SGFNode:
@property
def next_player(self):
"""Returns player to move"""
if "B" in self.properties or ("AB" in self.properties and not "W" in self.properties): # root or black moved
if "B" in self.properties or ("AB" in self.properties and "W" not in self.properties): # root or black moved
return "W"
else:
return "B"
@@ -288,7 +288,7 @@ class SGFNode:
@property
def player(self):
"""Returns player that moved last. nb root is considered white played if no handicap stones are placed"""
if "B" in self.properties or ("AB" in self.properties and not "W" in self.properties):
if "B" in self.properties or ("AB" in self.properties and "W" not in self.properties):
return "B"
else:
return "W"
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import List, Tuple, TypeVar
try:
import importlib.resources as pkg_resources
except:
except ImportError:
import importlib_resources as pkg_resources
T = TypeVar("T")
+5 -6
View File
@@ -1,4 +1,3 @@
import copy
import math
import random
import time
@@ -33,7 +32,7 @@ from katrain.core.constants import (
from katrain.core.game import Move
from katrain.core.lang import i18n
from katrain.core.utils import evaluation_class, format_visits, var_to_grid
from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text, cached_texture
from katrain.gui.kivyutils import draw_circle, draw_text, cached_texture
from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup
from katrain.gui.style import *
@@ -209,7 +208,7 @@ class BadukPanWidget(Widget):
Rectangle(
pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize),
size=(2 * evalsize, 2 * evalsize),
texture=cached_texture(f"img/dot.png"),
texture=cached_texture("img/dot.png"),
)
if innercol:
Color(*innercol)
@@ -217,7 +216,7 @@ class BadukPanWidget(Widget):
Rectangle(
pos=(self.gridpos_x[x] - inner_size, self.gridpos_y[y] - inner_size),
size=(2 * inner_size, 2 * inner_size),
texture=cached_texture(f"img/inner.png"),
texture=cached_texture("img/inner.png"),
)
def eval_color(self, points_lost, show_dots_for_class: List[bool] = None) -> Optional[List[float]]:
@@ -504,7 +503,7 @@ class BadukPanWidget(Widget):
katrain = self.katrain
game_ended = katrain.game.end_result
current_node = katrain.game.current_node
player, next_player = current_node.player, current_node.next_player
next_player = current_node.next_player
board_size_x, board_size_y = katrain.game.board_size
if len(self.gridpos_x) < board_size_x or len(self.gridpos_y) < board_size_y:
@@ -580,7 +579,7 @@ class BadukPanWidget(Widget):
)
if text_on and top_moves_show: # TODO: faster if not sized?
keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33}
player_sign = current_node.player_sign(current_node.next_player)
player_sign = current_node.player_sign(next_player)
if len(top_moves_show) == 1:
fmt = "[size={size:.0f}]{" + top_moves_show[0] + "}[/size]"
else:
+1 -1
View File
@@ -135,7 +135,7 @@ class ControlsPanel(BoxLayout):
lock_ai = katrain.config("trainer/lock_ai") and katrain.play_analyze_mode == MODE_PLAY
details = self.info.detailed and not lock_ai
info = ""
if current_node.move or current_node.is_root:
if move or current_node.is_root:
info = self.active_comment_node.comment(
teach=katrain.players_info[self.active_comment_node.player].being_taught, details=details
)
+2 -6
View File
@@ -1,6 +1,3 @@
import functools
from kivy.cache import Cache
from kivy.clock import Clock
from kivy.core.image import Image
from kivy.core.text import Label as CoreLabel
@@ -16,13 +13,12 @@ from kivy.properties import (
StringProperty,
)
from kivy.resources import resource_find
from kivy.uix.behaviors import ButtonBehavior, FocusBehavior, ToggleButtonBehavior
from kivy.uix.behaviors import ButtonBehavior, ToggleButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.spinner import Spinner
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from kivymd.uix.behaviors import CircularRippleBehavior, RectangularRippleBehavior
@@ -229,7 +225,7 @@ class KeyValueSpinner(Spinner):
def input_value(self):
try:
return self.value_refs[self.selected_index]
except:
except KeyError:
return ""
@property
+1 -1
View File
@@ -207,7 +207,7 @@ class QuickConfigGui(MDBoxLayout):
selected = 0
try:
selected = widget.value_refs.index(value)
except:
except: # noqa: E722
pass
widget.text = widget.values[selected]
else:
+2 -2
View File
@@ -1,6 +1,6 @@
from katrain.gui.widgets.filebrowser import I18NFileBrowser
from katrain.gui.widgets.graph import RankGraph, ScoreGraph
from katrain.gui.widgets.graph import ScoreGraph
from katrain.gui.widgets.movetree import MoveTree
from katrain.gui.widgets.selection_slider import SelectionSlider
__all__ = ["ScoreGraph", "RankGraph", "MoveTree", "I18NFileBrowser", "SelectionSlider"]
__all__ = ["ScoreGraph", "MoveTree", "I18NFileBrowser", "SelectionSlider"]
+5 -8
View File
@@ -38,7 +38,6 @@ a shortcut to the Documents directory added to the favorites bar::
:align: right
"""
import string
import warnings
from functools import partial
from os import walk
from os.path import dirname, expanduser, getmtime, isdir, join, sep
@@ -81,27 +80,25 @@ def get_drives():
drives = []
if platform == "win":
bitmask = windll.kernel32.GetLogicalDrives()
GetVolumeInformationW = windll.kernel32.GetVolumeInformationW
for letter in string.ascii_uppercase:
if bitmask & 1:
name = create_unicode_buffer(64)
# get name of the drive
drive = letter + u":"
res = GetVolumeInformationW(drive + sep, name, 64, None, None, None, None, 0)
drive = letter + ":"
if isdir(drive):
drives.append((drive, name.value))
bitmask >>= 1
elif platform == "linux":
drives.append((sep, sep))
drives.append((expanduser(u"~"), "~/"))
places = (sep + u"mnt", sep + u"media")
drives.append((expanduser("~"), "~/"))
places = (sep + "mnt", sep + "media")
for place in places:
if isdir(place):
for directory in next(walk(place))[1]:
drives.append((place + sep + directory, directory))
elif platform == "macosx" or platform == "ios":
drives.append((expanduser(u"~"), "~/"))
vol = sep + u"Volume"
drives.append((expanduser("~"), "~/"))
vol = sep + "Volume"
if isdir(vol):
for drive in next(walk(vol))[1]:
drives.append((vol + sep + drive, drive))
+2 -176
View File
@@ -7,9 +7,6 @@ from kivy.properties import BooleanProperty, Clock, ListProperty, NumericPropert
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from katrain.core.constants import OUTPUT_ERROR
from katrain.core.lang import rank_label
class Graph(Widget):
marker_font_size = NumericProperty(0)
@@ -128,11 +125,11 @@ class ScoreGraph(Graph):
xscale = self.width / max(len(score_values) - 1, 15)
available_height = self.height
score_line_points = [
[self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.score_scale),]
[self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.score_scale)]
for i, val in enumerate(score_values)
]
winrate_line_points = [
[self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.winrate_scale),]
[self.x + i * xscale, self.y + self.height / 2 + available_height / 2 * (val / self.winrate_scale)]
for i, val in enumerate(winrate_values)
]
self.score_points = sum(score_line_points, [])
@@ -158,144 +155,6 @@ class ScoreGraph(Graph):
self.winrate_dot_pos = winrate_dot_point
def averagemod(data):
sorteddata = sorted(data)
lendata = len(data)
return sum(sorteddata[int(lendata * 0.2) : int(lendata * 0.8) + 1]) / (
(int(lendata * 0.8) + 1) - int(lendata * 0.2)
) # average without the best and worst 20% of ranks
def gauss(data):
return math.exp(-1 * (data) ** 2)
class RankGraph(Graph):
black_rank_points = ListProperty([])
white_rank_points = ListProperty([])
segment_length = NumericProperty(80)
RANK_CAP = 5
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.calculate_trigger = Clock.create_trigger(lambda *args: self.rank_game(), 0.25)
self.rank_by_player = {}
@staticmethod
def calculate_rank_for_player(segment_stats, num_intersec, player):
non_obvious_moves = [
(nl, r, val)
for nl, r, val, pl in segment_stats
if nl is not None and val < (0.8 * (1 - (num_intersec - nl) / num_intersec * 0.5)) and pl == player
]
if not non_obvious_moves:
return None
num_legal, rank, value = zip(*non_obvious_moves)
rank = [min(r, nl * 0.09) for r, nl in zip(rank, num_legal)]
averagemod_rank = averagemod(rank)
averagemod_len_legal = averagemod(num_legal)
norm_avemod_len_legal = averagemod_len_legal / num_intersec
if averagemod_rank > 0.1:
rank_kyu = (
-0.97222
* math.log(averagemod_rank)
/ (0.24634 + averagemod_rank * gauss(3.3208 * (norm_avemod_len_legal)))
+ 12.703 * (norm_avemod_len_legal)
+ 11.198 * math.log(averagemod_rank)
+ 12.28 * gauss(2.379 * (norm_avemod_len_legal))
- 16.544
)
else:
rank_kyu = -4
return min(RankGraph.RANK_CAP, 1 - rank_kyu) # dan rank
@staticmethod
def calculate_ranks(segment_stats, num_intersec):
return {pl: RankGraph.calculate_rank_for_player(segment_stats, num_intersec, pl) for pl in "BW"}
def rank_game(self):
try:
nodes = self.nodes
parent_policy_per_move = [node.parent.policy_ranking if node.parent else None for node in nodes]
num_legal_moves = [
sum(pv >= 0 for pv, _ in policy_ranking) if policy_ranking else 0
for policy_ranking in parent_policy_per_move
]
policy_stats = [
[
(num_mv, rank, value, mv.player)
for rank, (value, mv) in enumerate(policy_ranking)
if mv == node.move
][0]
if policy_ranking and node.move
else (None, None, None, None)
for node, policy_ranking, num_mv in zip(nodes, parent_policy_per_move, num_legal_moves)
]
size = self.nodes[0].board_size
num_intersec = size[0] * size[1]
half_seg = self.segment_length // 2
ranks = {"B": [], "W": []}
dx = self.segment_length // 4
for segment_mid in range(dx, len(nodes), dx):
bounds = (max(0, segment_mid - half_seg), min(segment_mid + half_seg, len(nodes)))
num_analyzed = sum(num_mv is not None for num_mv, _, _, _ in policy_stats[bounds[0] : bounds[1] + 1])
if num_analyzed >= self.segment_length * 0.75:
for pl, rank in self.calculate_ranks(policy_stats[bounds[0] : bounds[1] + 1], num_intersec).items():
ranks[pl].append((segment_mid, rank))
self.rank_by_player = ranks
except Exception as e:
MDApp.get_running_app().gui.log(f"Exception while calculating rank: {e}", OUTPUT_ERROR)
self.redraw_trigger()
def update_value(self, node):
super().update_value(node)
self.trigger_calculate()
def trigger_calculate(self):
if self.opacity != 0: # recalc here on trigger and only if visible for speed
self.calculate_trigger()
def update_graph(self, *args):
if self.rank_by_player:
xscale = self.width / max(len(self.nodes) - 1, 15)
available_height = self.height
all_ranks = [rank for lst in self.rank_by_player.values() for seg, rank in lst if rank is not None]
if not all_ranks:
return
min_rank = math.floor(min(all_ranks))
max_rank = math.ceil(max(all_ranks))
if max_rank == min_rank:
min_rank -= 1
if (max_rank - min_rank) % 2 != 0: # make midpoint whole integer
if abs(max_rank - max(all_ranks)) < abs(min(all_ranks) - min_rank) and max_rank < self.RANK_CAP:
max_rank += 1
else:
min_rank -= 1
rank_range = max_rank - min_rank
self.ids.mid_marker.text = rank_label((max_rank + min_rank) / 2)
self.ids.top_marker.text = rank_label(max_rank) + ("+" if max_rank == self.RANK_CAP else "")
self.ids.bottom_marker.text = rank_label(min_rank)
graph_points = {}
for pl, rank_points in self.rank_by_player.items():
graph_points[pl] = [
[
self.x + i * xscale,
self.y + available_height * (val - min_rank) / rank_range if val is not None else math.nan,
]
for i, val in rank_points
]
self.black_rank_points = sum(graph_points["B"], [])
self.white_rank_points = sum(graph_points["W"], [])
else:
self.black_rank_points = []
self.white_rank_points = []
Builder.load_string(
"""
#:set GRAPH_CENTER_COLOR [0.5,0.5,0.5]
@@ -388,38 +247,5 @@ Builder.load_string(
pos:root.pos[0]+1, root.pos[1]
text: "{}%".format(50 - root.winrate_scale)
opacity: int(root.show_winrate)
<RankGraph>:
background_color: LIGHTER_BACKGROUND_COLOR
canvas:
Color:
rgba: WHITE
Line:
points: root.white_rank_points
width: dp(1.1)
Color:
rgba: BLACK
Line:
points: root.black_rank_points
width: dp(1.1)
# rank ticks
GraphMarkerLabel:
id: mid_marker
font_size: root.marker_font_size
color: YELLOW
pos: root.x + root.width - self.width-1, root.y + root.height*0.5 - self.height/2 + 2
text: '?' + i18n._('strength:kyu')
GraphMarkerLabel:
id: top_marker
font_size: root.marker_font_size
color: YELLOW
pos: root.x + root.width - self.width-1, root.pos[1]+root.height - self.font_size - 1
text: '?' + i18n._('strength:kyu')
GraphMarkerLabel:
id: bottom_marker
font_size: root.marker_font_size
color: YELLOW
pos: root.x + root.width - self.width-1, root.pos[1]
text: '?' + i18n._('strength:kyu')
"""
)
-6
View File
@@ -12,20 +12,14 @@ from kivymd.app import MDApp
from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text
from katrain.gui.style import (
BACKGROUND_COLOR,
DARKRED,
GREEN,
LIGHT_ORANGE,
LIGHTER_BACKGROUND_COLOR,
LIGHTGREY,
ORANGE,
OUTLINE_COLORS,
RED,
STONE_COLORS,
STONE_TEXT_COLORS,
WHITE,
YELLOW,
GREY,
)
-2
View File
@@ -1,8 +1,6 @@
from kivy.lang import Builder
from kivy.properties import BooleanProperty, ListProperty, NumericProperty
from kivy.uix.widget import Widget
from kivymd.uix.label import MDLabel
from kivymd.uix.selectioncontrol import Thumb
class SelectionSlider(Widget):
Binary file not shown.
@@ -762,3 +762,10 @@ msgstr "Expand/Collapse"
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -814,3 +814,10 @@ msgstr "Expand/Collapse"
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -360,6 +360,14 @@ msgstr "Setup New Game"
msgid "player names"
msgstr "Player Names"
#. hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. hint on player name input
msgid "white player name hint"
msgstr "White player's name"
msgid "board size"
msgstr "Board size"
Binary file not shown.
@@ -821,3 +821,10 @@ msgstr "Expand/Collapse"
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -847,3 +847,11 @@ msgstr "Expand/Collapse"
#. TODO - Menu option
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -804,3 +804,11 @@ msgstr "Expand/Collapse"
#. TODO - Menu option
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -775,3 +775,10 @@ msgstr "Expand/Collapse"
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
Binary file not shown.
@@ -811,3 +811,10 @@ msgstr "Expand/Collapse"
msgid "analysis:playtoend"
msgstr "Fast playout to game end"
#. TODO - hint on player name input
msgid "black player name hint"
msgstr "Black player's name"
#. TODO - hint on player name input
msgid "white player name hint"
msgstr "White player's name"
+2
View File
@@ -393,11 +393,13 @@
LabelledTextInput:
text: ''
id: black_player_name
hint_text: i18n._("black player name hint")
size_hint: 0.75, None
AnchorLayout:
LabelledTextInput:
text: ''
id: white_player_name
hint_text: i18n._("white player name hint")
size_hint: 0.75, None
DescriptionLabel:
text: i18n._("board size")
+1 -1
View File
@@ -5,7 +5,7 @@ from setuptools import find_packages, setup
package_data = {"": ["*.json", "*.kv", "*.wav"], "katrain": [], "tests": []}
packages = find_packages(exclude=["tests"])
version = re.search('^VERSION\s*=\s*"(.*)"', open("katrain/core/constants.py").read(), re.M).group(1)
version = re.search(r'^VERSION\s*=\s*"(.*)"', open("katrain/core/constants.py").read(), re.M).group(1)
def include_data_files(directory):
+1 -1
View File
@@ -1,6 +1,6 @@
import pytest
from katrain.core.base_katrain import OUTPUT_INFO, KaTrainBase
from katrain.core.base_katrain import KaTrainBase
from katrain.core.game import Game, IllegalMoveException, Move
from katrain.core.game_node import GameNode
+2 -3
View File
@@ -1,8 +1,7 @@
import os
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock
from katrain.core.base_katrain import KaTrainBase
from katrain.core.engine import KataGoEngine
from katrain.core.game import Game, KaTrainSGF
from katrain.core.sgf_parser import SGF, SGFNode
@@ -107,7 +106,7 @@ def test_old_server_style():
def test_ogs():
file = os.path.join(os.path.dirname(__file__), "data/ogs.sgf")
tree = SGF.parse_file(file)
SGF.parse_file(file)
def test_gibo():