rank graph
This commit is contained in:
1 parent
a333ca7142
commit
194547a0b6
20 files changed
+218
-108
No files matched your search
+1
-3
@@ -67,9 +67,7 @@ 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.widgets.graph import ScoreGraph
|
||||
from katrain.gui.widgets.movetree import MoveTree
|
||||
from katrain.gui.widgets.filebrowser import I18NFileBrowser
|
||||
from katrain.gui.widgets import *
|
||||
from katrain.gui.badukpan import AnalysisControls, BadukPanControls, BadukPanWidget
|
||||
from katrain.gui.controlspanel import ControlsPanel
|
||||
|
||||
|
||||
+22
-33
@@ -136,6 +136,15 @@ class GameNode(SGFNode):
|
||||
if win_rate is not None:
|
||||
return f"{'B' if win_rate > 0.5 else 'W'} {max(win_rate,1-win_rate):.1%}"
|
||||
|
||||
def move_policy_stats(self) -> Tuple[Optional[int], float, List]:
|
||||
single_move = self.move
|
||||
if single_move and self.parent:
|
||||
policy_ranking = self.parent.policy_ranking
|
||||
for ix, (p, m) in enumerate(policy_ranking):
|
||||
if m == single_move:
|
||||
return ix + 1, p, policy_ranking
|
||||
return None, 0.0, []
|
||||
|
||||
def make_pv(self, player, pv, interactive):
|
||||
pvtext = f"{player}{' '.join(pv)}"
|
||||
if interactive:
|
||||
@@ -160,44 +169,24 @@ class GameNode(SGFNode):
|
||||
points_lost = self.points_lost
|
||||
if sgf and points_lost > 0.5:
|
||||
text += i18n._("Info:point loss").format(points_lost=points_lost) + "\n"
|
||||
text += (
|
||||
i18n._("Info:top move").format(
|
||||
top_move=previous_top_move["move"],
|
||||
score=self.format_score(previous_top_move["scoreLead"]),
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
top_move = previous_top_move["move"]
|
||||
score = self.format_score(previous_top_move["scoreLead"])
|
||||
text += i18n._("Info:top move").format(top_move=top_move, score=score,) + "\n"
|
||||
else:
|
||||
text += i18n._("Info:best move") + "\n"
|
||||
if previous_top_move.get("pv") and (sgf or details):
|
||||
text += (
|
||||
i18n._("Info:PV").format(
|
||||
pv=self.make_pv(single_move.player, previous_top_move["pv"], interactive)
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
pv = self.make_pv(single_move.player, previous_top_move["pv"], interactive)
|
||||
text += i18n._("Info:PV").format(pv=pv) + "\n"
|
||||
|
||||
if sgf or details or teach:
|
||||
policy_ranking = self.parent.policy_ranking
|
||||
currmove_policy_with_ix = [
|
||||
(ix + 1, p)
|
||||
for (p, m), ix in zip(policy_ranking, range(len(policy_ranking)))
|
||||
if m == single_move
|
||||
]
|
||||
if currmove_policy_with_ix:
|
||||
text += (
|
||||
i18n._("Info:policy rank").format(
|
||||
rank=currmove_policy_with_ix[0][0], probability=currmove_policy_with_ix[0][1]
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
if not currmove_policy_with_ix or currmove_policy_with_ix[0] != 1 and (sgf or details):
|
||||
text += (
|
||||
i18n._("Info:policy best").format(
|
||||
move=policy_ranking[0][1].gtp(), probability=policy_ranking[0][0]
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
currmove_pol_rank, currmove_pol_prob, policy_ranking = self.move_policy_stats()
|
||||
if currmove_pol_rank is not None:
|
||||
policy_rank_msg = i18n._("Info:policy rank")
|
||||
text += policy_rank_msg.format(rank=currmove_pol_rank, probability=currmove_pol_prob) + "\n"
|
||||
if currmove_pol_rank is None or currmove_pol_rank != 1 and (sgf or details):
|
||||
policy_best_msg = i18n._("Info:policy best")
|
||||
pol_move, pol_prob = policy_ranking[0][1].gtp(), policy_ranking[0][0]
|
||||
text += policy_best_msg.format(move=pol_move, probability=pol_prob) + "\n"
|
||||
if self.auto_undo and sgf:
|
||||
text += i18n._("Info:teaching undo") + "\n"
|
||||
top_pv = self.analysis_ready and self.candidate_moves[0].get("pv")
|
||||
|
||||
+17
-6
@@ -498,7 +498,7 @@
|
||||
spacing: CP_SPACING
|
||||
player_box_height: max(50, 0.075 * root.height)
|
||||
timer_box_height: max(50, 0.1 * root.height)
|
||||
graph_box_height: max(100, 0.2 * root.height)
|
||||
graph_height: max(75, 0.2 * root.height - 25)
|
||||
stats_box_height: max(50, 0.15 * root.height)
|
||||
tab_option_height: max(15,root.height / 30)
|
||||
BoxLayout: # -- Players
|
||||
@@ -540,15 +540,26 @@
|
||||
opacity: 0 if self.parent.mode == MODE_PLAY else 1
|
||||
CollapsablePanel:
|
||||
id: graph_panel
|
||||
height_open: root.graph_box_height
|
||||
height_open: self.header.height + graph.height + rank_graph.height
|
||||
closed_label: 'closedlabel:scoregraph'
|
||||
options: ['score','winrate']
|
||||
option_colors: [SCORE_COLOR,WINRATE_COLOR]
|
||||
option_active: [True,False]
|
||||
options: ['score','winrate','rank_est']
|
||||
option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR]
|
||||
option_active: [True,False,False]
|
||||
options_height: root.tab_option_height
|
||||
on_option_state: graph.show_graphs(args[1])
|
||||
on_option_state:
|
||||
graph.show_graphs(args[1])
|
||||
graph.hidden = not (args[1]['score'] or args[1]['winrate'])
|
||||
rank_graph.hidden = not args[1]['rank_est']
|
||||
ScoreGraph:
|
||||
id: graph
|
||||
opacity: 0 if self.hidden else 1
|
||||
size_hint_y: None
|
||||
height: 0.0001 if self.hidden else root.graph_height
|
||||
RankGraph:
|
||||
id: rank_graph
|
||||
opacity: 0 if self.hidden else 1
|
||||
size_hint_y: None
|
||||
height: 0.0001 if self.hidden else root.graph_height
|
||||
CollapsablePanel:
|
||||
id: stats_panel
|
||||
height_open: root.stats_box_height
|
||||
|
||||
+26
-17
@@ -360,6 +360,8 @@ class CollapsablePanel(MDBoxLayout):
|
||||
option_active = ListProperty([])
|
||||
option_colors = ListProperty([])
|
||||
|
||||
contents = ListProperty([])
|
||||
|
||||
closed_label = StringProperty("Closed Panel")
|
||||
|
||||
size_hint_y_open = NumericProperty(1)
|
||||
@@ -370,7 +372,7 @@ class CollapsablePanel(MDBoxLayout):
|
||||
open_icon = "img/Next-5.png"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.header, self.contents, self.open_close_button = None, None, None
|
||||
self.open_close_button, self.header = None, None
|
||||
self.option_buttons = []
|
||||
super().__init__(**kwargs)
|
||||
self.orientation = "vertical"
|
||||
@@ -381,10 +383,26 @@ class CollapsablePanel(MDBoxLayout):
|
||||
option_active=self.build_options,
|
||||
options_spacing=self.build_options,
|
||||
)
|
||||
self.bind(state=self.build, size_hint_y_open=self.build, height_open=self.build)
|
||||
self.bind(state=self._on_state,size_hint_y_open=self._on_size, height_open=self._on_size)
|
||||
MDApp.get_running_app().bind(language=lambda *_: Clock.schedule_once(self.build_options, 0))
|
||||
self.build_options()
|
||||
|
||||
def _on_state(self,*_args):
|
||||
self.build()
|
||||
self.trigger_select(ix=None)
|
||||
|
||||
def _on_size(self,*_args):
|
||||
height, size_hint_y = 1, None
|
||||
if self.state == "open" and self.contents:
|
||||
if self.height_open:
|
||||
height = self.height_open
|
||||
else:
|
||||
size_hint_y = self.size_hint_y_open
|
||||
else:
|
||||
height = self.header.height
|
||||
self.height, self.size_hint_y = height, size_hint_y
|
||||
|
||||
|
||||
@property
|
||||
def option_state(self):
|
||||
return {option: active for option, active in zip(self.options, self.option_active)}
|
||||
@@ -396,7 +414,7 @@ class CollapsablePanel(MDBoxLayout):
|
||||
button.state = "down" if state_dict[option] else "normal"
|
||||
self.trigger_select(ix=None)
|
||||
|
||||
def build_options(self, *args, **kwargs):
|
||||
def build_options(self, *args):
|
||||
self.header = CollapsablePanelHeader(
|
||||
height=self.options_height, size_hint_y=None, spacing=self.options_spacing, padding=[1, 0, 0, 0]
|
||||
)
|
||||
@@ -422,13 +440,12 @@ class CollapsablePanel(MDBoxLayout):
|
||||
self.bind(state=lambda *_args: self.open_close_button.setter("icon")(None, self.open_close_icon()))
|
||||
self.build()
|
||||
|
||||
def build(self, *args, **kwargs):
|
||||
def build(self, *args):
|
||||
self.header.clear_widgets()
|
||||
if self.state == "open":
|
||||
for button in self.option_buttons:
|
||||
self.header.add_widget(button)
|
||||
self.header.add_widget(Label()) # spacer
|
||||
self.trigger_select(ix=None)
|
||||
else:
|
||||
self.header.add_widget(
|
||||
Label(
|
||||
@@ -439,24 +456,16 @@ class CollapsablePanel(MDBoxLayout):
|
||||
|
||||
super().clear_widgets()
|
||||
super().add_widget(self.header)
|
||||
height, size_hint_y = 1, None
|
||||
if self.state == "open" and self.contents:
|
||||
super().add_widget(self.contents)
|
||||
if self.height_open:
|
||||
height = self.height_open
|
||||
else:
|
||||
size_hint_y = self.size_hint_y_open
|
||||
else:
|
||||
height = self.header.height
|
||||
self.height, self.size_hint_y = height, size_hint_y
|
||||
for w in self.contents:
|
||||
super().add_widget(w)
|
||||
self._on_size()
|
||||
|
||||
def open_close_icon(self):
|
||||
return self.open_icon if self.state == "open" else self.close_icon
|
||||
|
||||
def add_widget(self, widget, index=0, **_kwargs):
|
||||
if self.contents:
|
||||
raise ValueError("CollapsablePanel can only have one child")
|
||||
self.contents = widget
|
||||
self.contents.append(widget)
|
||||
self.build()
|
||||
|
||||
def set_state(self, state="toggle"):
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from katrain.gui.widgets.graph import ScoreGraph, RankGraph
|
||||
from katrain.gui.widgets.movetree import MoveTree
|
||||
from katrain.gui.widgets.filebrowser import I18NFileBrowser
|
||||
from katrain.gui.widgets.selection_slider import SelectionSlider
|
||||
|
||||
__all__ = ["ScoreGraph", "RankGraph", "MoveTree", "I18NFileBrowser", "SelectionSlider"]
|
||||
+119
-49
@@ -1,22 +1,64 @@
|
||||
import math
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import BooleanProperty, ListProperty, NumericProperty, Clock
|
||||
from kivy.properties import BooleanProperty, ListProperty, NumericProperty, Clock, StringProperty
|
||||
from kivymd.app import MDApp
|
||||
|
||||
from katrain.core.lang import i18n
|
||||
from katrain.gui.kivyutils import BackgroundMixin
|
||||
import threading
|
||||
|
||||
|
||||
class ScoreGraph(BackgroundMixin):
|
||||
whalf = NumericProperty(0)
|
||||
bhalf = NumericProperty(0)
|
||||
mid = NumericProperty(0)
|
||||
class Graph(BackgroundMixin):
|
||||
marker_font_size = NumericProperty(0)
|
||||
background_image = StringProperty("img/graph_bg.png")
|
||||
|
||||
nodes = ListProperty([])
|
||||
hidden = BooleanProperty(False)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._lock = threading.Lock()
|
||||
self.bind(pos=self.update_graph, size=self.update_graph)
|
||||
|
||||
def initialize_from_game(self, root):
|
||||
self.nodes = [root]
|
||||
node = root
|
||||
while node.children:
|
||||
node = node.ordered_children[0]
|
||||
self.nodes.append(node)
|
||||
self.highlighted_index = 0
|
||||
|
||||
def update_graph(self, *args):
|
||||
pass
|
||||
|
||||
def update_value(self, node):
|
||||
with self._lock:
|
||||
self.highlighted_index = index = node.depth
|
||||
self.nodes.extend([None] * max(0, index - (len(self.nodes) - 1)))
|
||||
self.nodes[index] = node
|
||||
if index > 1 and node.parent: # sometimes things go so fast
|
||||
backfill, bfnode = index - 1, node.parent
|
||||
while bfnode is not None and self.nodes[backfill] != bfnode:
|
||||
self.nodes[backfill] = bfnode
|
||||
backfill -= 1
|
||||
bfnode = bfnode.parent
|
||||
|
||||
if index + 1 < len(self.nodes) and (
|
||||
node is None or not node.children or self.nodes[index + 1] != node.ordered_children[0]
|
||||
):
|
||||
self.nodes = self.nodes[: index + 1] # on branch switching, don't show history from other branch
|
||||
if index == len(self.nodes) - 1: # possibly just switched branch or the line above triggered
|
||||
while node.children: # add children back
|
||||
node = node.ordered_children[0]
|
||||
self.nodes.append(node)
|
||||
Clock.schedule_once(self.update_graph, 0)
|
||||
|
||||
|
||||
class ScoreGraph(Graph):
|
||||
show_score = BooleanProperty(True)
|
||||
show_winrate = BooleanProperty(True)
|
||||
|
||||
nodes = ListProperty([])
|
||||
score_points = ListProperty([])
|
||||
winrate_points = ListProperty([])
|
||||
|
||||
@@ -30,11 +72,6 @@ class ScoreGraph(BackgroundMixin):
|
||||
|
||||
navigate_move = ListProperty([None, 0, 0, 0])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._lock = threading.Lock()
|
||||
self.bind(pos=self.update_graph, size=self.update_graph)
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
if self.collide_point(*touch.pos):
|
||||
ix, _ = min(enumerate(self.score_points[::2]), key=lambda ix_v: abs(ix_v[1] - touch.x))
|
||||
@@ -58,14 +95,6 @@ class ScoreGraph(BackgroundMixin):
|
||||
katrain.update_state()
|
||||
self.navigate_move = [None, 0, 0, 0]
|
||||
|
||||
def initialize_from_game(self, root):
|
||||
self.nodes = [root]
|
||||
node = root
|
||||
while node.children:
|
||||
node = node.ordered_children[0]
|
||||
self.nodes.append(node)
|
||||
self.highlighted_index = 0
|
||||
|
||||
def show_graphs(self, keys):
|
||||
self.show_score = keys["score"]
|
||||
self.show_winrate = keys["winrate"]
|
||||
@@ -124,27 +153,30 @@ class ScoreGraph(BackgroundMixin):
|
||||
)
|
||||
self.winrate_dot_pos = winrate_dot_point
|
||||
|
||||
def update_value(self, node):
|
||||
with self._lock:
|
||||
self.highlighted_index = index = node.depth
|
||||
self.nodes.extend([None] * max(0, index - (len(self.nodes) - 1)))
|
||||
self.nodes[index] = node
|
||||
if index > 1 and node.parent: # sometimes things go so fast
|
||||
backfill, bfnode = index - 1, node.parent
|
||||
while bfnode is not None and self.nodes[backfill] != bfnode:
|
||||
self.nodes[backfill] = bfnode
|
||||
backfill -= 1
|
||||
bfnode = bfnode.parent
|
||||
|
||||
if index + 1 < len(self.nodes) and (
|
||||
node is None or not node.children or self.nodes[index + 1] != node.ordered_children[0]
|
||||
):
|
||||
self.nodes = self.nodes[: index + 1] # on branch switching, don't show history from other branch
|
||||
if index == len(self.nodes) - 1: # possibly just switched branch or the line above triggered
|
||||
while node.children: # add children back
|
||||
node = node.ordered_children[0]
|
||||
self.nodes.append(node)
|
||||
Clock.schedule_once(self.update_graph, 0)
|
||||
class RankGraph(Graph):
|
||||
black_rank_points = ListProperty([])
|
||||
white_rank_points = ListProperty([])
|
||||
rank_scale = NumericProperty(5)
|
||||
rank_mid = NumericProperty(5)
|
||||
|
||||
@staticmethod
|
||||
def rank_label(rank):
|
||||
if rank <= 0:
|
||||
return f"{1-rank}{i18n._('strength:dan')}"
|
||||
else:
|
||||
return f"{rank}{i18n._('strength:dan')}"
|
||||
|
||||
def update_graph(self, *args):
|
||||
nodes = self.nodes
|
||||
if nodes:
|
||||
score_values = [n.score if n and n.score else math.nan for n in nodes]
|
||||
score_nn_values = [n.score for n in nodes if n and n.score]
|
||||
score_values_range = min(score_nn_values or [0]), max(score_nn_values or [0])
|
||||
|
||||
self.ids.mid_marker.text = self.rank_label(5)
|
||||
self.ids.bottom_marker.text = self.rank_label(10)
|
||||
self.ids.top_marker.text = self.rank_label(-2)
|
||||
|
||||
|
||||
Builder.load_string(
|
||||
@@ -152,16 +184,17 @@ Builder.load_string(
|
||||
#:set GRAPH_CENTER_COLOR [0.5,0.5,0.5]
|
||||
#:set GRAPH_DOT_COLOR [0.85, 0.3, 0.3,1]
|
||||
|
||||
#:import LIGHTER_BACKGROUND_COLOR katrain.gui.style.LIGHTER_BACKGROUND_COLOR
|
||||
#:import BOX_BACKGROUND_COLOR katrain.gui.style.BOX_BACKGROUND_COLOR
|
||||
#:import SCORE_COLOR katrain.gui.style.SCORE_COLOR
|
||||
#:import WINRATE_COLOR katrain.gui.style.WINRATE_COLOR
|
||||
#:import BLACK katrain.gui.style.BLACK
|
||||
#:import WHITE katrain.gui.style.WHITE
|
||||
#:import YELLOW katrain.gui.style.YELLOW
|
||||
|
||||
<ScoreGraph>:
|
||||
|
||||
<Graph>:
|
||||
background_color: BOX_BACKGROUND_COLOR
|
||||
whalf: self.y + self.height*0.25
|
||||
bhalf: self.y + self.height*0.75
|
||||
mid: self.y + self.height*0.5
|
||||
right_edge: self.x + self.width
|
||||
marker_font_size: 0.1 * self.height
|
||||
canvas:
|
||||
Color:
|
||||
@@ -169,7 +202,11 @@ Builder.load_string(
|
||||
Rectangle:
|
||||
pos: self.pos
|
||||
size: self.size
|
||||
source: 'img/graph_bg.png'
|
||||
source: root.background_image
|
||||
|
||||
|
||||
|
||||
<ScoreGraph>:
|
||||
canvas.after:
|
||||
Color:
|
||||
rgba: SCORE_COLOR
|
||||
@@ -202,26 +239,26 @@ Builder.load_string(
|
||||
GraphMarkerLabel:
|
||||
font_size: root.marker_font_size
|
||||
color: SCORE_COLOR
|
||||
pos: root.right_edge - self.width-1, root.pos[1]+root.height - self.font_size - 1
|
||||
pos: root.x + root.width - self.width-1, root.pos[1]+root.height - self.font_size - 1
|
||||
text: 'B+{}'.format(root.score_scale)
|
||||
opacity: int(root.show_score)
|
||||
GraphMarkerLabel:
|
||||
font_size: root.marker_font_size
|
||||
color: SCORE_COLOR
|
||||
pos: root.right_edge - self.width-1, root.mid - self.height/2 + 2
|
||||
pos: root.x + root.width - self.width-1, root.y + root.height*0.5 - self.height/2 + 2
|
||||
text: i18n._('Jigo')
|
||||
opacity: int(root.show_score)
|
||||
GraphMarkerLabel:
|
||||
font_size: root.marker_font_size
|
||||
color: SCORE_COLOR
|
||||
pos: root.right_edge - self.width-1, root.pos[1]
|
||||
pos: root.x + root.width - self.width-1, root.pos[1]
|
||||
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
|
||||
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:
|
||||
@@ -230,5 +267,38 @@ 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.after:
|
||||
Color:
|
||||
rgba: WHITE
|
||||
Line:
|
||||
points: root.white_rank_points
|
||||
width: 1.1
|
||||
Color:
|
||||
rgba: BLACK
|
||||
Line:
|
||||
points: root.black_rank_points
|
||||
width: 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')
|
||||
"""
|
||||
)
|
||||
Binary file not shown.
@@ -568,3 +568,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Binary file not shown.
@@ -611,3 +611,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Binary file not shown.
@@ -139,6 +139,9 @@ msgstr "Score"
|
||||
msgid "tab:winrate"
|
||||
msgstr "Win Rate"
|
||||
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
|
||||
msgid "tab:points"
|
||||
msgstr "Point Loss"
|
||||
|
||||
|
||||
Binary file not shown.
@@ -606,3 +606,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Binary file not shown.
@@ -645,3 +645,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Binary file not shown.
@@ -583,3 +583,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Binary file not shown.
@@ -608,3 +608,7 @@ msgstr "Download Models"
|
||||
#. TODO
|
||||
msgid "All models downloaded"
|
||||
msgstr "All available models already downloaded"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:rank_est"
|
||||
msgstr "Rank Estimate"
|
||||
Reference in new issue
Block a user