Exemple #1
0
    def write_sgf(
        self, path: str, trainer_config: Optional[Dict] = None,
    ):
        if trainer_config is None:
            trainer_config = self.katrain.config("trainer")
        save_feedback = trainer_config["save_feedback"]
        eval_thresholds = trainer_config["eval_thresholds"]

        def player_name(player_info):
            return f"{i18n._(player_info.player_type)} ({i18n._(player_info.player_subtype)})"

        if "KaTrain" in self.root.get_property("AP", ""):
            for bw in "BW":
                self.root.set_property("P" + bw, player_name(self.katrain.players_info[bw]))
                player_info = self.katrain.players_info[bw]
                if player_info.player_type == PLAYER_AI:
                    self.root.set_property(bw + "R", rank_label(player_info.calculated_rank))

        player_names = {bw: re.sub(r"['<>:\"/\\|?*]", "", self.root.get_property("P" + bw, bw)) for bw in "BW"}
        game_name = f"katrain_{player_names['B']} vs {player_names['W']} {self.game_id}"
        file_name = os.path.abspath(os.path.join(path, f"{game_name}.sgf"))
        os.makedirs(os.path.dirname(file_name), exist_ok=True)

        show_dots_for = {
            bw: trainer_config.get("eval_show_ai", True) or self.katrain.players_info[bw].human for bw in "BW"
        }
        sgf = self.root.sgf(
            save_comments_player=show_dots_for, save_comments_class=save_feedback, eval_thresholds=eval_thresholds
        )
        with open(file_name, "w", encoding="utf-8") as f:
            f.write(sgf)
        return i18n._("sgf written").format(file_name=file_name)
Exemple #2
0
    def update_root_properties(self):
        def player_name(player_info):
            if player_info.name and player_info.player_type == PLAYER_HUMAN:
                return player_info.name
            else:
                return f"{i18n._(player_info.player_type)} ({i18n._(player_info.player_subtype)})"

        root_properties = self.root.properties
        x_properties = {}
        for bw in "BW":
            if not self.external_game:
                x_properties["P" +
                             bw] = player_name(self.katrain.players_info[bw]
                                               ) + SGF_INTERNAL_COMMENTS_MARKER
                player_info = self.katrain.players_info[bw]
                if player_info.player_type == PLAYER_AI:
                    x_properties[bw + "R"] = rank_label(
                        player_info.calculated_rank)
        if "+" in str(self.end_result):
            x_properties["RE"] = self.end_result
        self.root.properties = {
            **root_properties,
            **{k: [v]
               for k, v in x_properties.items()}
        }
Exemple #3
0
 def update_players(self, *_args):
     for bw, player_info in self.katrain.players_info.items():
         self.players[bw].player_type = player_info.player_type
         self.players[bw].player_subtype = player_info.player_subtype
         self.players[bw].name = player_info.name
         self.players[bw].rank = (
             player_info.sgf_rank if player_info.player_type == PLAYER_HUMAN
             else rank_label(player_info.calculated_rank))
Exemple #4
0
 def estimate_rank_from_options(self, *_args):
     strategy = self.ai_select.selected[1]
     try:
         options = self.collect_properties(self)  # [strategy]
     except InputParseError:
         self.estimated_rank_label.text = "??"
         return
     prefix = f"ai/{strategy}/"
     options = {k[len(prefix) :]: v for k, v in options.items() if k.startswith(prefix)}
     dan_rank = ai_rank_estimation(strategy, options)
     self.estimated_rank_label.text = rank_label(dan_rank)
Exemple #5
0
    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 = []
Exemple #6
0
    def generate_filename(self):
        def player_name(player_info):
            if player_info.name and player_info.player_type == PLAYER_HUMAN:
                return player_info.name
            else:
                return f"{i18n._(player_info.player_type)} ({i18n._(player_info.player_subtype)})"

        root_properties = self.root.properties
        x_properties = {}
        for bw in "BW":
            if not self.external_game:
                x_properties["P" + bw] = player_name(self.katrain.players_info[bw]) + SGF_INTERNAL_COMMENTS_MARKER
                player_info = self.katrain.players_info[bw]
                if player_info.player_type == PLAYER_AI:
                    x_properties[bw + "R"] = rank_label(player_info.calculated_rank)
        if "+" in str(self.end_result):
            x_properties["RE"] = self.end_result
        x_properties["KTV"] = ANALYSIS_FORMAT_VERSION
        self.root.properties = {**root_properties, **{k: [v] for k, v in x_properties.items()}}
        player_names = {
            bw: re.sub(r"[\u200b\u3164'<>:\"/\\|?*]", "", self.root.get_property("P" + bw, bw)) for bw in "BW"
        }
        base_game_name = f"{PROGRAM_NAME}_{player_names['B']} vs {player_names['W']}"
        return f"{base_game_name} {self.game_id}.sgf"
Exemple #7
0
    def _refresh(self, _dt=0):
        game = self.katrain.game
        thresholds = self.katrain.config("trainer/eval_thresholds")

        sum_stats, histogram, player_ptloss = game_report(
            game, depth_filter=self.depth_filter, thresholds=thresholds)
        labels = [
            f"≥ {pt}" if pt > 0 else f"< {thresholds[-2]}" for pt in thresholds
        ]

        table = GridLayout(cols=3, rows=6 + len(thresholds))
        colors = [
            [cp * 0.75 for cp in col[:3]] + [1]
            for col in Theme.EVAL_COLORS[self.katrain.config("trainer/theme")]
        ]

        table.add_widget(
            TableHeaderLabel(text="", background_color=Theme.BACKGROUND_COLOR))
        table.add_widget(
            TableHeaderLabel(text=i18n._("header:keystats"),
                             background_color=Theme.BACKGROUND_COLOR))
        table.add_widget(
            TableHeaderLabel(text="", background_color=Theme.BACKGROUND_COLOR))

        for i, (label, fmt, stat, scale, more_is_better) in enumerate([
            ("accuracy", "{:.1f}", "accuracy", 100, True),
            ("meanpointloss", "{:.1f}", "mean_ptloss", 5, False),
            ("aitopmove", "{:.1%}", "ai_top_move", 1, True),
            ("aitop5", "{:.1%}", "ai_top5_move", 1, True),
        ]):

            statcell = {
                bw: TableStatLabel(
                    text=fmt.format(sum_stats[bw][stat])
                    if stat in sum_stats[bw] else "",
                    side=side,
                    value=sum_stats[bw].get(stat, 0),
                    scale=scale,
                    bar_color=Theme.STAT_BETTER_COLOR if
                    (sum_stats[bw].get(stat, 0) <
                     sum_stats[Move.opponent_player(bw)].get(stat, 0))
                    ^ more_is_better else Theme.STAT_WORSE_COLOR,
                    background_color=Theme.BOX_BACKGROUND_COLOR,
                )
                for (bw, side) in zip("BW", ["left", "right"])
            }
            table.add_widget(statcell["B"])
            table.add_widget(
                TableCellLabel(text=i18n._(f"stat:{label}"),
                               background_color=Theme.BOX_BACKGROUND_COLOR))
            table.add_widget(statcell["W"])

        table.add_widget(
            TableHeaderLabel(text=i18n._("header:num moves"),
                             background_color=Theme.BACKGROUND_COLOR))
        table.add_widget(
            TableHeaderLabel(text=i18n._("stats:pointslost"),
                             background_color=Theme.BACKGROUND_COLOR))
        table.add_widget(
            TableHeaderLabel(text=i18n._("header:num moves"),
                             background_color=Theme.BACKGROUND_COLOR))

        for i, (col, label, pt) in enumerate(
                zip(colors[::-1], labels[::-1], thresholds[::-1])):
            statcell = {
                bw: TableStatLabel(
                    text=str(histogram[i][bw]),
                    side=side,
                    value=histogram[i][bw],
                    scale=len(player_ptloss[bw]) + 1e-6,
                    bar_color=col,
                    background_color=Theme.BOX_BACKGROUND_COLOR,
                )
                for (bw, side) in zip("BW", ["left", "right"])
            }
            table.add_widget(statcell["B"])
            table.add_widget(TableCellLabel(text=label, background_color=col))
            table.add_widget(statcell["W"])

        self.stats.clear_widgets()
        self.stats.add_widget(table)

        for bw, player_info in self.katrain.players_info.items():
            self.player_infos[bw].player_type = player_info.player_type
            self.player_infos[bw].captures = ""  # ;)
            self.player_infos[bw].player_subtype = player_info.player_subtype
            self.player_infos[bw].name = player_info.name
            self.player_infos[bw].rank = (
                player_info.sgf_rank if player_info.player_type == PLAYER_HUMAN
                else rank_label(player_info.calculated_rank))

        # if not done analyzing, check again in 1s
        if not self.katrain.engine.is_idle():
            Clock.schedule_once(self._refresh, 1)