Last active
March 7, 2018 23:51
-
-
Save BorisNA/20cac069bd16c1142d177252df950478 to your computer and use it in GitHub Desktop.
Implemented new layout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from Tkinter import * | |
from ScrolledText import * | |
import tkFont | |
import sys,time | |
from functools import partial | |
from toolbox import * | |
from toolbox import _ | |
import os | |
from gtp import gtp | |
import ConfigParser | |
import threading, Queue | |
import mss | |
import mss.tools | |
bg='#C0C0C0' | |
from goban import * | |
def get_node_number(node): | |
k=0 | |
while node: | |
node=node[0] | |
if (node.get_move()[0]!=None) and (node.get_move()[1]!=None): | |
k+=1 | |
else: | |
break | |
return k | |
def get_node(root,number=0): | |
if number==0:return root | |
node=root | |
k=0 | |
while k!=number: | |
if not node: | |
return False | |
node=node[0] | |
k+=1 | |
return node | |
class OpenChart(): | |
def __init__(self,parent,data,nb_moves,current_move=0): | |
self.parent=parent | |
self.nb_moves=nb_moves | |
self.data=data | |
self.current_move=current_move | |
self.initialize() | |
def close(self): | |
log("closing popup") | |
self.popup.destroy() | |
self.parent.all_popups.remove(self) | |
log("done") | |
def initialize(self): | |
Config = ConfigParser.ConfigParser() | |
Config.read(config_file) | |
popup_width=self.parent.winfo_width() | |
popup_height=self.parent.winfo_height()/2+10 | |
self.popup=Toplevel(self.parent) | |
popup=self.popup | |
popup.geometry(str(popup_width)+'x'+str(popup_height)) | |
bg=popup.cget("background") | |
#popup.configure(background=bg) | |
top_frame=Frame(popup) | |
top_frame.pack() | |
top_frame.pack() | |
self.graph_mode=StringVar() | |
available_graphs=[] | |
for data in self.data: | |
if data: | |
if ("score_estimation" in data) or ("upper_bound_score" in data) or ("lower_bound_score" in data): | |
self.graph_mode.set(_("Score estimation")) # initialize | |
available_graphs.append(_("Score estimation")) | |
break | |
for data in self.data: | |
if data: | |
if "position_win_rate" in data: | |
self.graph_mode.set(_("Win rate")) # initialize | |
available_graphs.append(_("Win rate")) | |
break | |
for data in self.data: | |
if data: | |
if "winrate_delta" in data: | |
if data["player_color"]=="b": | |
available_graphs.append(_("Black win rate delta")) | |
break | |
for data in self.data: | |
if data: | |
if "winrate_delta" in data: | |
if data["player_color"]=="w": | |
available_graphs.append(_("White win rate delta")) | |
break | |
for data in self.data: | |
if data: | |
if "monte_carlo_win_rate" in data: | |
available_graphs.append(_("Monte Carlo win rate")) | |
break | |
for data in self.data: | |
if data: | |
if "mcwr_delta" in data: | |
if data["player_color"]=="w": | |
available_graphs.append(_("Black Monte Carlo win rate delta")) | |
break | |
for data in self.data: | |
if data: | |
if "mcwr_delta" in data: | |
if data["player_color"]=="b": | |
available_graphs.append(_("White Monte Carlo win rate delta")) | |
break | |
for data in self.data: | |
if data: | |
if "value_network_win_rate" in data: | |
available_graphs.append(_("Value Network win rate")) | |
break | |
for data in self.data: | |
if data: | |
if "vnwr_delta" in data: | |
if data["player_color"]=="w": | |
available_graphs.append(_("Black Value Network win rate delta")) | |
break | |
for data in self.data: | |
if data: | |
if "vnwr_delta" in data: | |
if data["player_color"]=="b": | |
available_graphs.append(_("White Value Network win rate delta")) | |
break | |
self.graph_selection=apply(OptionMenu,(top_frame,self.graph_mode)+tuple(available_graphs)) | |
self.graph_selection.pack(side=LEFT, padx=5) | |
self.graph_mode.trace("w", lambda a,b,c: self.display()) | |
if not self.graph_mode.get(): | |
self.graph_mode.set(available_graphs[0]) | |
self.chart = Canvas(popup,bg='white',bd=0, borderwidth=0) | |
#self.chart.grid(sticky=N+S+W+E) | |
self.chart.pack(fill=BOTH,expand=1, padx=5) | |
self.chart.bind("<Configure>",self.display) | |
bottom_frame=Frame(popup) | |
bottom_frame.pack(anchor=W) | |
self.status_bar=Label(bottom_frame,text='',background=bg) | |
self.status_bar.pack(anchor=W) | |
bottom_frame.pack() | |
self.clear_status() | |
self.popup.bind('<Control-q>', self.save_as_png) | |
self.popup.protocol("WM_DELETE_WINDOW", self.close) | |
popup.focus() | |
def set_status(self,event=None,msg=''): | |
self.status_bar.config(text=msg) | |
def clear_status(self,event=None): | |
self.status_bar.config(text=_("<Ctrl+Q> to save the graph as an image.")) | |
def goto_move(self,event=None,move=None): | |
if move: | |
log("goto move",move) | |
self.parent.parent.lift() | |
self.parent.goto_move(move_number=move) | |
def display_vertical_winrate_graduation(self,border,height,width): | |
#drawing vertical graduation | |
lpix=int(border/4) | |
graduations=[x*10 for x in range(10+1)] | |
y0=height+1000 | |
x0=border/2 | |
x1=width-border/2 | |
for g in graduations: | |
y1=height-border-g*(height-2*border)/100. | |
if y0-y1>=border: | |
self.chart.create_text(x0,y1, text=str(g)+"%",fill='black',font=("Arial", str(lpix))) | |
self.chart.create_text(x1,y1, text=str(g)+"%",fill='black',font=("Arial", str(lpix))) | |
#self.chart.create_line(x0, y1, x1, y1, fill='black') | |
y0=y1 | |
def display_vertical_score_graduation(self,border,height,width,maximum): | |
#drawing vertical graduation | |
lpix=int(border/4) | |
graduations=[x*20 for x in range(int(-maximum/20.),int((maximum+20)/20.))] | |
y0=height+1000 | |
x0=border/2 | |
x1=width-border/2 | |
middle=height-border-(height-2*border)/2 | |
for g in graduations: | |
y1=height-border-g*(height-2*border)/100. | |
y1=g/2*(height-2*border)/maximum | |
y1=middle-y1 | |
if y0-y1>=border: | |
self.chart.create_text(x0,y1, text=str(g),fill='black',font=("Arial", str(lpix))) | |
self.chart.create_text(x1,y1, text=str(g),fill='black',font=("Arial", str(lpix))) | |
#self.chart.create_line(x0, y1, x1, y1, fill='black') | |
y0=y1 | |
def display(self,event=None): | |
if event: | |
width=event.width | |
height=event.height | |
self.width=width | |
self.height=height | |
else: | |
width=self.width | |
height=self.height | |
border=min(max(20,width/25),200) | |
space=1.0*(width-2*border)/self.nb_moves | |
lpix=int(border/4) | |
for item in self.chart.find_all(): | |
self.chart.delete(item) | |
self.chart.create_line(0, 0, width, 0, fill='#000000',width=4) | |
self.chart.create_line(0, height, width, height, fill='#000000',width=4) | |
self.chart.create_line(0, 0, 0, height, fill='#000000',width=4) | |
self.chart.create_line(width, 0, width, height, fill='#000000',width=4) | |
y00=height-border | |
x0=border+(self.current_move-1)*space | |
x1=x0+space | |
y1=border | |
yellow_bar=self.chart.create_rectangle(x0, y00, x1, y1, fill='#FFFF00',outline='#FFFF00') | |
mode=_(self.graph_mode.get()) | |
if mode in (_("Black win rate delta").decode("utf"),_("White win rate delta").decode("utf")): | |
moves=self.display_winrate_delta(border,height,width) | |
elif mode==_("Win rate").decode("utf"): | |
moves=self.display_winrate_graph(border,height,width,lpix) | |
elif mode==_("Score estimation").decode("utf"): | |
moves=self.display_score_graph(border,height,width,lpix) | |
elif mode==_("Monte Carlo win rate").decode("utf"): | |
moves=self.display_monte_carlo_winrate_graph(border,height,width,lpix) | |
elif mode==_("Value Network win rate").decode("utf"): | |
moves=self.display_value_network_winrate_graph(border,height,width,lpix) | |
elif mode in (_("Black Monte Carlo win rate delta").decode("utf"),_("White Monte Carlo win rate delta").decode("utf")): | |
moves=self.display_monte_carlo_delta(border,height,width) | |
elif mode in (_("Black Value Network win rate delta").decode("utf"),_("White Value Network win rate delta").decode("utf")): | |
moves=self.display_value_network_delta(border,height,width) | |
self.display_horizontal_graduation(moves,height,width,border,lpix) | |
self.display_axis(moves,height,width,border,lpix) | |
def display_value_network_delta(self,border,height,width): | |
moves=[] | |
space=1.0*(width-2*border)/(self.nb_moves+1) | |
if self.graph_mode.get()=="Black Value Network win rate delta": | |
player_color='b' | |
else: | |
player_color='w' | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if (one_data["player_color"]==player_color) and ("vnwr_delta" in one_data): | |
position_win_rate=one_data["value_network_win_rate"] | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space*2 | |
y0=height-border | |
y1=height-border-position_win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
delta=one_data["vnwr_delta"] | |
if player_color.lower()=="b": | |
msg=_("Move %i: Black's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
else: | |
msg=_("Move %i: White's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
if delta<>0: | |
y2=y1-delta*(height-2*border)/100. | |
if delta<0: | |
red_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='red',outline='#aa0000') | |
msg2=_("The computer believes it's own move win rate would be %.2fpp higher.")%(-delta) | |
self.chart.tag_bind(red_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(red_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(red_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
else: | |
green_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='#00ff00',outline='#00aa00') | |
msg2=_("The computer believes the actual move is %.2fpp better than it's best move.")%(delta) | |
self.chart.tag_bind(green_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(green_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(green_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_monte_carlo_delta(self,border,height,width): | |
moves=[] | |
space=1.0*(width-2*border)/(self.nb_moves+1) | |
if self.graph_mode.get()=="Black Monte Carlo win rate delta": | |
player_color='b' | |
else: | |
player_color='w' | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if (one_data["player_color"]==player_color) and ("mcwr_delta" in one_data): | |
position_win_rate=one_data["monte_carlo_win_rate"] | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space*2 | |
y0=height-border | |
y1=height-border-position_win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
delta=one_data["mcwr_delta"] | |
if player_color.lower()=="b": | |
msg=_("Move %i: Black's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
else: | |
msg=_("Move %i: White's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
if delta<>0: | |
y2=y1-delta*(height-2*border)/100. | |
if delta<0: | |
red_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='red',outline='#aa0000') | |
msg2=_("The computer believes it's own move win rate would be %.2fpp higher.")%(-delta) | |
self.chart.tag_bind(red_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(red_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(red_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
else: | |
green_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='#00ff00',outline='#00aa00') | |
msg2=_("The computer believes the actual move is %.2fpp better than it's best move.")%(delta) | |
self.chart.tag_bind(green_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(green_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(green_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_winrate_delta(self,border,height,width): | |
moves=[] | |
space=1.0*(width-2*border)/(self.nb_moves+1) | |
if self.graph_mode.get()=="Black win rate delta": | |
player_color='b' | |
else: | |
player_color='w' | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if (one_data["player_color"]==player_color) and ("winrate_delta" in one_data): | |
position_win_rate=one_data["position_win_rate"] | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space*2 | |
y0=height-border | |
y1=height-border-position_win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
delta=one_data["winrate_delta"] | |
if player_color.lower()=="b": | |
msg=_("Move %i: Black's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
else: | |
msg=_("Move %i: White's move win rate: %s, computer's move win rate: %s")%(move,str(position_win_rate+delta)+"%",str(position_win_rate)+"%") | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
if delta<>0: | |
y2=y1-delta*(height-2*border)/100. | |
if delta<0: | |
red_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='red',outline='#aa0000') | |
msg2=_("The computer believes it's own move win rate would be %.2fpp higher.")%(-delta) | |
self.chart.tag_bind(red_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(red_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(red_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
else: | |
green_bar=self.chart.create_rectangle(x0, y1, x1, y2, fill='#00ff00',outline='#00aa00') | |
msg2=_("The computer believes the actual move is %.2fpp better than it's best move.")%(delta) | |
self.chart.tag_bind(green_bar, "<Enter>", partial(self.set_status,msg=msg2)) | |
self.chart.tag_bind(green_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(green_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_value_network_winrate_graph(self,border,height,width,lpix): | |
moves=[] | |
space=1.0*(width-2*border)/self.nb_moves | |
self.chart.create_text(len(_("Black win rate"))*lpix/2,border/2, text=_("Black win rate"),fill='black',font=("Arial", str(lpix))) | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if "value_network_win_rate" in one_data: | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space | |
win_rate=one_data["value_network_win_rate"] | |
if one_data["player_color"]=="w": | |
win_rate=100.-win_rate | |
color=_("White") | |
else: | |
color=_("Black") | |
player_win_rate=float(int(win_rate*100)/100.) | |
y0=height-border | |
y1=height-border-win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
#msg="Move "+str(move)+" ("+color+"), black/white win rate: "+str(player_win_rate)+"%/"+str(100-player_win_rate)+"%" | |
msg=(_("Move %i (%s), black/white win rate: ")%(move,color))+str(win_rate)+"%/"+str(100-player_win_rate)+"%" | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_monte_carlo_winrate_graph(self,border,height,width,lpix): | |
moves=[] | |
space=1.0*(width-2*border)/self.nb_moves | |
self.chart.create_text(len(_("Black win rate"))*lpix/2,border/2, text=_("Black win rate"),fill='black',font=("Arial", str(lpix))) | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if "monte_carlo_win_rate" in one_data: | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space | |
win_rate=one_data["monte_carlo_win_rate"] | |
if one_data["player_color"]=="w": | |
win_rate=100.-win_rate | |
color=_("White") | |
else: | |
color=_("Black") | |
player_win_rate=float(int(win_rate*100)/100.) | |
y0=height-border | |
y1=height-border-win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
#msg="Move "+str(move)+" ("+color+"), black/white win rate: "+str(player_win_rate)+"%/"+str(100-player_win_rate)+"%" | |
msg=(_("Move %i (%s), black/white win rate: ")%(move,color))+str(win_rate)+"%/"+str(100-player_win_rate)+"%" | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_winrate_graph(self,border,height,width,lpix): | |
moves=[] | |
space=1.0*(width-2*border)/self.nb_moves | |
self.chart.create_text(len(_("Black win rate"))*lpix/2,border/2, text=_("Black win rate"),fill='black',font=("Arial", str(lpix))) | |
x00=border | |
y00=height-border-(height-2*border)/2. | |
for one_data in self.data: | |
if "position_win_rate" in one_data: | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space | |
position_win_rate=one_data["position_win_rate"] | |
if one_data["player_color"]=="w": | |
position_win_rate=100.-position_win_rate | |
color=_("White") | |
else: | |
color=_("Black") | |
player_win_rate=float(int(position_win_rate*100)/100.) | |
y0=height-border | |
y1=height-border-position_win_rate*(height-2*border)/100. | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
#msg="Move "+str(move)+" ("+color+"), black/white win rate: "+str(player_win_rate)+"%/"+str(100-player_win_rate)+"%" | |
msg=(_("Move %i (%s), black/white win rate: ")%(move,color))+str(position_win_rate)+"%/"+str(100-player_win_rate)+"%" | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y1, x1, y1, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y1, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y1 | |
#drawing vertical graduation | |
self.display_vertical_winrate_graduation(border,height,width) | |
return moves | |
def display_score_graph(self,border,height,width,lpix): | |
self.chart.create_text(border+len(_("Black win"))*lpix/2,border+lpix, text=_("Black win"),fill='black',font=("Arial", str(lpix))) | |
self.chart.create_text(border+len(_("White win"))*lpix/2,height-border-lpix, text=_("White win"),fill='black',font=("Arial", str(lpix))) | |
moves=[] | |
#checking graph limits | |
maximum=-1000 | |
for one_data in self.data: | |
if "score_estimation" in one_data: | |
maximum=max(maximum,max([abs(x) for x in (one_data["upper_bound_score"],one_data["lower_bound_score"],one_data["score_estimation"])])) | |
maximum+=5 | |
space=1.0*(width-2*border)/self.nb_moves | |
middle=height-border-(height-2*border)/2 | |
x00=border | |
y00=middle | |
for one_data in self.data: | |
if "score_estimation" in one_data: | |
move=one_data["move"] | |
moves.append(move) | |
x0=border+(move-1)*space | |
x1=x0+space | |
estimated_score=one_data["score_estimation"] | |
upper_bound_score=one_data["upper_bound_score"] | |
lower_bound_score=one_data["lower_bound_score"] | |
y0=middle-lower_bound_score*(height-2*border)/2./maximum | |
y1=middle-upper_bound_score*(height-2*border)/2./maximum | |
y2=middle-estimated_score*(height-2*border)/2./maximum | |
y3=min(middle,y0,y1,y2) | |
y4=max(middle,y0,y1,y2) | |
white_bar=self.chart.create_rectangle(x0, y3, x1, y4, fill='#eeeeee',outline='') | |
if y0!=y1: | |
grey_bar=self.chart.create_rectangle(x0, y0, x1, y1, fill='#aaaaaa',outline='grey') | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.chart.create_line(x0, y2, x1, y2, fill='#0000ff',width=2) | |
self.chart.create_line(x0, y2, x00, y00, fill='#0000ff') | |
x00=x1 | |
y00=y2 | |
if one_data["player_color"]=="w": | |
color=_("White") | |
else: | |
color=_("Black") | |
if estimated_score>=0: | |
msg=(_("Move %i (%s), estimated score: ")%(move,color)) | |
msg+="B+"+str(estimated_score) | |
if (lower_bound_score!=upper_bound_score): | |
msg+=" [B%+.1f, B%+.1f]"%(lower_bound_score,upper_bound_score) | |
else: | |
msg=(_("Move %i (%s), estimated score: ")%(move,color)) | |
msg+="W+"+str(abs(estimated_score)) | |
if (lower_bound_score!=upper_bound_score): | |
msg+=" [W%+.1f, W%+.1f]"%(-lower_bound_score,-upper_bound_score) | |
self.chart.tag_bind(white_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(white_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(white_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
if y0!=y1: | |
self.chart.tag_bind(grey_bar, "<Enter>", partial(self.set_status,msg=msg)) | |
self.chart.tag_bind(grey_bar, "<Leave>", self.clear_status) | |
self.chart.tag_bind(grey_bar, "<Button-1>",partial(self.goto_move,move=move)) | |
self.display_vertical_score_graduation(border,height,width,maximum) | |
return moves | |
def display_axis(self,moves,height,width,border,lpix): | |
#drawing axis | |
x0=border | |
y0=height-border | |
y1=border | |
self.chart.create_line(x0, y0, x0, y1, fill='black') | |
x1=width-border | |
self.chart.create_line(x1, y0, x1, y1, fill='black') | |
self.chart.create_line(x0, y0, x1, y0, fill='black') | |
self.chart.create_line(x0, (y0+y1)/2, x1, (y0+y1)/2, fill='black') | |
def display_horizontal_graduation(self,moves,height,width,border,lpix): | |
#drawing horizontal graduation | |
graduations=[x for x in moves] | |
x0=-1000 | |
y0=height-border/2 | |
y1=height-border | |
for g in graduations: | |
x1=border+(g)*(width-2*border)/self.nb_moves*1.0 | |
if x1-x0>=border: | |
self.chart.create_text(x1,y0, text=str(g),fill='black',font=("Arial", str(lpix))) | |
self.chart.create_line(x1, y1, x1, (y0+y1)/2, fill='black') | |
x0=x1 | |
def save_as_png(self,e=None): | |
top=Tk() | |
top.withdraw() | |
filename=save_png_file(filename=self.graph_mode.get()+' graph.png',parent=top) | |
top.destroy() | |
canvas2png(self.chart,filename) | |
class OpenMove(): | |
def __init__(self,parent,move,dim,sgf,goban_size=200): | |
self.parent=parent | |
self.move=move | |
self.dim=dim | |
self.sgf=sgf | |
self.goban_size=goban_size | |
self.available_bots=[] | |
for bot in get_available("ReviewBot"): | |
self.available_bots.append(bot) | |
self.initialize() | |
def lock(self): | |
self.undo_button.config(state='disabled') | |
self.menu.config(state='disabled') | |
self.play_button.config(state='disabled') | |
self.white_button.config(state='disabled') | |
self.black_button.config(state='disabled') | |
self.evaluation_button.config(state='disabled') | |
if (not self.white_autoplay) or (not self.black_autoplay): | |
self.selfplay_button.config(state='disabled') | |
self.goban.bind("<Button-1>",self.do_nothing) | |
self.goban.bind("<Button-2>",self.do_nothing) | |
self.locked=True | |
def do_nothing(self): | |
pass | |
def unlock(self): | |
self.undo_button.config(state='normal') | |
self.menu.config(state='normal') | |
self.play_button.config(state='normal') | |
self.white_button.config(state='normal') | |
self.black_button.config(state='normal') | |
self.selfplay_button.config(state='normal') | |
self.evaluation_button.config(state='normal') | |
self.goban.bind("<Button-1>",self.click) | |
self.goban.bind("<Button-2>",self.undo) | |
self.locked=False | |
def close(self): | |
log("closing popup") | |
self.display_queue.put(0) | |
self.popup.destroy() | |
for bot in self.bots: | |
bot.close() | |
self.parent.all_popups.remove(self) | |
log("done") | |
def undo(self,event=None): | |
log("UNDO") | |
if len(self.history)<1: | |
return | |
elif len(self.history)==1: | |
self.undo_button.config(state='disabled') | |
popup=self.popup | |
self.grid,self.markup=self.history.pop() | |
self.next_color=3-self.next_color | |
self.goban.display(self.grid,self.markup) | |
for bot in self.bots: | |
bot.undo() | |
def click_button(self,bot): | |
dim=self.dim | |
self.lock() | |
self.display_queue.put(2) | |
color=self.next_color | |
move=bot.click(color) | |
if move.lower() not in ["pass","resign"]: | |
i,j=gtp2ij(move) | |
#log('i,j=',i,j) | |
for other_bot in self.bots: | |
if other_bot!=bot: | |
try: | |
other_bot.place(move,color) | |
except: | |
pass | |
self.history.append([copy(self.grid),copy(self.markup)]) | |
place(self.grid,i,j,color) | |
self.grid[i][j]=color | |
self.markup=[["" for row in range(dim)] for col in range(dim)] | |
self.markup[i][j]=0 | |
self.next_color=3-color | |
else: | |
if move.lower() == "resign": | |
bot.undo_resign() | |
else: | |
bot.undo() | |
if color==1: | |
self.display_queue.put(bot.name+" ("+_("Black")+"): "+move.lower()) | |
else: | |
self.display_queue.put(bot.name+" ("+_("White")+"): "+move.lower()) | |
if self.white_autoplay and self.black_autoplay: | |
if move.lower() not in ["pass","resign"]: | |
log("SELF PLAY") | |
self.display_queue.put(2) | |
one_thread=threading.Thread(target=self.click_button,args=(self.menu_bots[self.selected_bot.get()],)) | |
self.popup.after(0,one_thread.start()) | |
return | |
else: | |
log("End of SELF PLAY") | |
self.click_selfplay() | |
self.display_queue.put(1) | |
self.unlock() | |
return | |
else: | |
self.display_queue.put(1) | |
self.unlock() | |
return | |
def click(self,event): | |
dim=self.dim | |
#add/remove black stone | |
#check pointer location | |
i,j=self.goban.xy2ij(event.x,event.y) | |
color=self.next_color | |
if 0 <= i <= dim-1 and 0 <= j <= dim-1: | |
#inside the grid | |
#what is under the pointer ? | |
if self.grid[i][j] not in (1,2): | |
#nothing, so we add a black stone | |
for bot in self.bots: | |
if bot.place(ij2gtp((i,j)),color)==False: | |
del self.menu_bots[bot.name] | |
self.menu.pack_forget() | |
if len(self.menu_bots): | |
self.selected_bot.set(self.menu_bots.keys()[0]) | |
self.selected_bot=StringVar() | |
#self.menu=OptionMenu(self.menu_wrapper,self.selected_bot,*tuple(self.menu_bots.keys())) | |
self.menu=apply(OptionMenu, (self.menu_wrapper, self.selected_bot) + tuple(self.menu_bots.keys())) | |
self.menu.pack(fill=BOTH,expand=1) | |
else: | |
self.menu.config(state='disabled') | |
self.play_button.config(state='disabled') | |
self.white_button.config(state='disabled') | |
self.black_button.config(state='disabled') | |
self.selfplay_button.config(state='disabled') | |
self.history.append([copy(self.grid),copy(self.markup)]) | |
place(self.grid,i,j,color) | |
self.grid[i][j]=color | |
self.markup=[["" for row in range(dim)] for col in range(dim)] | |
self.markup[i][j]=0 | |
self.goban.display(self.grid,self.markup) | |
self.next_color=3-color | |
self.undo_button.config(state='normal') | |
if color==1: | |
if self.white_autoplay: | |
threading.Thread(target=self.click_button,args=(self.menu_bots[self.selected_bot.get()],)).start() | |
#self.click_button(self.menu_bots[self.selected_bot.get()]) | |
else: | |
if self.black_autoplay: | |
threading.Thread(target=self.click_button,args=(self.menu_bots[self.selected_bot.get()],)).start() | |
#self.click_button(self.menu_bots[self.selected_bot.get()]) | |
def set_status(self,msg,event=None): | |
self.status_bar.config(text=msg) | |
def clear_status(self): | |
self.status_bar.config(text="") | |
def click_play_one_move(self): | |
log("Asking",self.selected_bot.get(),"to play one move") | |
self.white_button.config(relief=RAISED) | |
self.black_button.config(relief=RAISED) | |
self.selfplay_button.config(relief=RAISED) | |
self.black_autoplay=False | |
self.white_autoplay=False | |
threading.Thread(target=self.click_button,args=(self.menu_bots[self.selected_bot.get()],)).start() | |
#self.click_button(self.menu_bots[self.selected_bot.get()]) | |
def click_white_answer(self): | |
if self.white_button.cget("relief")!=SUNKEN: | |
self.white_button.config(relief=SUNKEN) | |
self.white_autoplay=True | |
else: | |
self.white_button.config(relief=RAISED) | |
self.white_autoplay=False | |
self.black_autoplay=False | |
self.black_button.config(relief=RAISED) | |
self.selfplay_button.config(relief=RAISED) | |
def click_black_answer(self): | |
if self.black_button.cget("relief")!=SUNKEN: | |
self.black_button.config(relief=SUNKEN) | |
self.black_autoplay=True | |
else: | |
self.black_button.config(relief=RAISED) | |
self.black_autoplay=False | |
self.white_autoplay=False | |
self.white_button.config(relief=RAISED) | |
self.selfplay_button.config(relief=RAISED) | |
def click_selfplay(self): | |
self.white_button.config(relief=RAISED) | |
self.black_button.config(relief=RAISED) | |
if self.selfplay_button.cget("relief")!=SUNKEN: | |
if self.locked: | |
self.selfplay_button.config(relief=RAISED) | |
return | |
self.selfplay_button.config(relief=SUNKEN) | |
self.black_autoplay=True | |
self.white_autoplay=True | |
self.selfplay_button.config(text=_('Abort')) | |
threading.Thread(target=self.click_button,args=(self.menu_bots[self.selected_bot.get()],)).start() | |
else: | |
self.selfplay_button.config(relief=RAISED) | |
self.black_autoplay=False | |
self.white_autoplay=False | |
self.selfplay_button.config(text=_('Self play')) | |
def click_evaluation(self): | |
log("Asking",self.selected_bot.get(),"for quick estimation") | |
self.lock() | |
self.display_queue.put(2) | |
threading.Thread(target=self.evaluation,args=(self.menu_bots[self.selected_bot.get()],)).start() | |
def evaluation(self,bot): | |
color=self.next_color | |
result=bot.quick_evaluation(color) | |
if color==1: | |
self.display_queue.put(result) | |
else: | |
self.display_queue.put(result) | |
self.unlock() | |
def initialize(self): | |
Config = ConfigParser.ConfigParser() | |
Config.read(config_file) | |
sgf=self.sgf | |
komi=self.sgf.get_komi() | |
gameroot=self.sgf.get_root() | |
self.popup=Toplevel(self.parent) | |
popup=self.popup | |
dim=self.dim | |
move=self.move | |
#popup.configure(background=bg) | |
bg=popup.cget("background") | |
self.locked=False | |
panel=Frame(popup, padx=5, pady=5, height=2, bd=1, relief=SUNKEN) | |
panel.configure(background=bg) | |
undo_button=Button(panel, text=_('Undo'),command=self.undo) | |
undo_button.grid(column=0,row=1,sticky=E+W) | |
undo_button.config(state='disabled') | |
undo_button.bind("<Enter>",lambda e: self.set_status(_("Undo last move. Shortcut: mouse middle button."))) | |
undo_button.bind("<Leave>",lambda e: self.clear_status()) | |
self.bots=[] | |
self.menu_bots={} | |
row=10 | |
value={"slow":" (%s)"%_("Slow profile"),"fast":" (%s)"%_("Fast profile")} | |
for available_bot in self.available_bots: | |
row+=2 | |
one_bot=available_bot['openmove'](self.sgf,available_bot['profile']) | |
one_bot.start() | |
self.bots.append(one_bot) | |
if one_bot.okbot: | |
self.menu_bots[one_bot.name+value[available_bot['profile']]]=one_bot | |
if len(self.menu_bots)>0: | |
row+=10 | |
Label(panel,text=" ").grid(column=0,row=row,sticky=E+W) | |
row+=1 | |
self.selected_bot=StringVar() | |
self.selected_bot.set(self.menu_bots.keys()[0]) | |
self.menu_wrapper=Frame(panel) | |
self.menu_wrapper.grid(row=row,column=0,sticky=E+W) | |
self.menu_wrapper.bind("<Enter>",lambda e: self.set_status(_("Select a bot."))) | |
self.menu_wrapper.bind("<Leave>",lambda e: self.clear_status()) | |
#self.menu=OptionMenu(self.menu_wrapper,self.selected_bot,*tuple(self.menu_bots.keys())) | |
self.menu=apply(OptionMenu, (self.menu_wrapper, self.selected_bot) + tuple(self.menu_bots.keys())) | |
self.menu.pack(fill=BOTH,expand=1) | |
row+=1 | |
Label(panel,text=" ").grid(column=0,row=row,sticky=E+W) | |
row+=1 | |
self.play_button=Button(panel, text=_('Play one move'),command=self.click_play_one_move) | |
self.play_button.grid(column=0,row=row,sticky=E+W) | |
self.play_button.bind("<Enter>",lambda e: self.set_status(_("Ask the bot to play one move."))) | |
self.play_button.bind("<Leave>",lambda e: self.clear_status()) | |
row+=1 | |
self.white_button=Button(panel, text=_('Play as white'),command=self.click_white_answer) | |
self.white_button.grid(column=0,row=row,sticky=E+W) | |
self.white_button.bind("<Enter>",lambda e: self.set_status(_("Ask the bot to play as White."))) | |
self.white_button.bind("<Leave>",lambda e: self.clear_status()) | |
row+=1 | |
self.black_button=Button(panel, text=_('Play as black'),command=self.click_black_answer) | |
self.black_button.grid(column=0,row=row,sticky=E+W) | |
self.black_button.bind("<Enter>",lambda e: self.set_status(_("Ask the bot to play as Black."))) | |
self.black_button.bind("<Leave>",lambda e: self.clear_status()) | |
row+=1 | |
self.selfplay_button=Button(panel, text=_('Self play'),command=self.click_selfplay) | |
self.selfplay_button.grid(column=0,row=row,sticky=E+W) | |
self.selfplay_button.bind("<Enter>",lambda e: self.set_status(_("Ask the bot to play alone."))) | |
self.selfplay_button.bind("<Leave>",lambda e: self.clear_status()) | |
row+=1 | |
Label(panel,text=" ").grid(column=0,row=row,sticky=E+W) | |
row+=1 | |
self.evaluation_button=Button(panel, text=_('Quick evaluation'),command=self.click_evaluation) | |
self.evaluation_button.grid(column=0,row=row,sticky=E+W) | |
self.evaluation_button.bind("<Enter>",lambda e: self.set_status(_("Ask the bot for a quick evaluation"))) | |
self.evaluation_button.bind("<Leave>",lambda e: self.clear_status()) | |
self.black_autoplay=False | |
self.white_autoplay=False | |
panel.grid(column=1,row=1,sticky=N+S) | |
goban3 = Goban(dim,master=popup, width=10, height=10,bg=bg,bd=0, borderwidth=0) | |
goban3.space=self.goban_size/(dim+1+1) | |
goban3.grid(column=2,row=1,sticky=N+S+E+W) | |
popup.grid_rowconfigure(1, weight=1) | |
popup.grid_columnconfigure(2, weight=1) | |
self.popup.bind('<Control-q>', self.save_as_png) | |
goban3.bind("<Enter>",lambda e: self.set_status(_("<Ctrl+Q> to save the goban as an image."))) | |
goban3.bind("<Leave>",lambda e: self.clear_status()) | |
Label(popup,text=' ',background=bg).grid(row=0,column=3) | |
Label(popup,text=' ',background=bg).grid(row=2,column=0) | |
self.status_bar=Label(popup,text='',background=bg) | |
self.status_bar.grid(row=2,column=1,columnspan=2,sticky=W) | |
grid3=[[0 for row in range(dim)] for col in range(dim)] | |
markup3=[["" for row in range(dim)] for col in range(dim)] | |
log("========================") | |
log("opening move",move) | |
board, noneed = sgf_moves.get_setup_and_moves(self.sgf) | |
for colour, move0 in board.list_occupied_points(): | |
if move0 is None: | |
continue | |
row, col = move0 | |
if colour=='b': | |
color=1 | |
else: | |
color=2 | |
place(grid3,row,col,color) | |
m=0 | |
for m in range(1,move): | |
one_move=get_node(gameroot,m) | |
if one_move==False: | |
log("(0)leaving because one_move==False") | |
return | |
ij=one_move.get_move()[1] | |
#log(ij) | |
if one_move.get_move()[0]=='b': | |
color=1 | |
else: | |
color=2 | |
for bot in self.bots: | |
bot.place(ij2gtp(ij),color) | |
if ij==None: | |
log("(1)skipping because ij==None",ij) | |
continue | |
i,j=ij | |
place(grid3,i,j,color) | |
if m>0: | |
markup3[i][j]=0 | |
try: | |
if get_node(gameroot,move).get_move()[0].lower()=="w": | |
self.next_color=2 | |
else: | |
self.next_color=1 | |
except: | |
log("error when trying to figure out next color to play, so black is selected") | |
self.next_color=1 | |
goban3.display(grid3,markup3) | |
self.goban=goban3 | |
self.grid=grid3 | |
self.markup=markup3 | |
self.undo_button=undo_button | |
popup.protocol("WM_DELETE_WINDOW", self.close) | |
goban3.bind("<Button-1>",self.click) | |
goban3.bind("<Button-2>",self.undo) | |
#goban3.bind("<Button-3>",lambda event: click_on_undo(popup)) | |
self.history=[] | |
self.goban.bind("<Configure>",self.redraw) | |
popup.focus() | |
self.display_queue=Queue.Queue(1) | |
self.parent.after(100,self.wait_for_display) | |
def wait_for_display(self): | |
try: | |
msg=self.display_queue.get(False) | |
if msg==0: | |
pass | |
elif msg==1: | |
self.goban.display(self.grid,self.markup) | |
self.parent.after(250,self.wait_for_display) | |
elif msg==2: | |
self.goban.display(self.grid,self.markup,True) | |
self.parent.after(250,self.wait_for_display) | |
else: | |
show_info(msg,self.popup) | |
self.goban.display(self.grid,self.markup) | |
self.parent.after(0,self.wait_for_display) | |
except: | |
self.parent.after(250,self.wait_for_display) | |
def redraw(self, event): | |
new_size=min(event.width,event.height) | |
new_space=new_size/(self.dim+1+1) | |
self.goban.space=new_space | |
new_anchor_x=(event.width-new_size)/2. | |
self.goban.anchor_x=new_anchor_x | |
new_anchor_y=(event.height-new_size)/2. | |
self.goban.anchor_y=new_anchor_y | |
self.goban.redraw() | |
def save_as_png(self,e=None): | |
top=Tk() | |
top.withdraw() | |
filename = save_png_file(parent=top,filename='variation_move'+str(self.move)+'.png') | |
top.destroy() | |
canvas2png(self.goban,filename) | |
class DualView(Frame): | |
def __init__(self,parent,filename,goban_size=200): | |
Frame.__init__(self,parent) | |
self.parent=parent | |
self.filename=filename | |
self.goban_size=goban_size | |
global Config, goban | |
Config = ConfigParser.ConfigParser() | |
Config.read(config_file) | |
goban.fuzzy=float(Config.get("Review", "FuzzyStonePlacement")) | |
self.variation_color_mode=Config.get("Review", "VariationsColoring") | |
self.inverted_mouse_wheel=Config.getboolean('Review', 'InvertedMouseWheel') | |
self.initialize() | |
self.current_move=1 | |
self.display_move(self.current_move) | |
self.pressed=0 | |
self.parent.focus() | |
def close_app(self): | |
for popup in self.all_popups[:]: | |
popup.close() | |
self.destroy() | |
self.parent.destroy() | |
def prev_10_move(self,event=None): | |
self.current_move=max(1,self.current_move-10) | |
self.pressed=time.time() | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def prev_move(self,event=None): | |
if self.current_move>1: | |
self.pressed=time.time() | |
self.current_move-=1 | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def next_10_move(self,event=None): | |
self.current_move=min(get_node_number(self.gameroot),self.current_move+10) | |
self.pressed=time.time() | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def next_move(self,event=None): | |
if self.current_move<get_node_number(self.gameroot): | |
self.pressed=time.time() | |
self.current_move+=1 | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def first_move(self,event=None): | |
self.current_move=1 | |
self.pressed=time.time() | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def final_move(self,event=None): | |
self.current_move=get_node_number(self.gameroot) | |
self.pressed=time.time() | |
pf=partial(self.goto_move,move_number=self.current_move,pressed=self.pressed) | |
self.parent.after(0,lambda: pf()) | |
def goto_move(self,move_number,pressed=None): | |
self.move_number.config(text=str(move_number)+'/'+str(get_node_number(self.gameroot))) | |
if not pressed: | |
self.current_move=move_number | |
self.display_move(self.current_move) | |
for popup in self.all_popups: | |
if isinstance(popup,OpenChart): | |
popup.current_move=self.current_move | |
#self.parent.after(0,popup.display) | |
popup.display() | |
elif self.pressed==pressed: | |
self.display_move(self.current_move) | |
for popup in self.all_popups: | |
if isinstance(popup,OpenChart): | |
popup.current_move=self.current_move | |
#self.parent.after(0,popup.display) | |
popup.display() | |
self.update_idletasks() | |
def leave_variation(self,goban,grid,markup): | |
self.comment_box2.delete(1.0, END) | |
self.parent.bind("<Up>", lambda e: None) | |
self.parent.bind("<Down>", lambda e: None) | |
self.current_variation_sequence=None | |
self.clear_status() | |
goban.display(grid,markup) | |
def show_variation(self,event,goban,grid,markup,i,j): | |
sequence=markup[i][j] | |
self.show_variation_move(goban,grid,markup,i,j,len(sequence)) | |
def show_variation_move(self,goban,grid,markup,i,j,move): | |
sequence=markup[i][j] | |
temp_grid=copy(grid) | |
temp_markup=copy(markup) | |
for u in range(self.dim): | |
for v in range(self.dim): | |
if temp_markup[u][v]!=0: | |
temp_markup[u][v]='' | |
k=1 | |
for color,(u,v),s,comment,displaycolor,letter_color in sequence[:move]: | |
#temp_grid[u][v]=color | |
place(temp_grid,u,v,color) | |
temp_markup[u][v]=k | |
k+=1 | |
goban.display(temp_grid,temp_markup) | |
self.comment_box2.delete(1.0, END) | |
if comment: | |
self.comment_box2.insert(END,comment) | |
u=i+goban.mesh[i][j][0] | |
v=j+goban.mesh[i][j][1] | |
local_area=goban.draw_point(u,v,1,color="",outline="") | |
goban.tag_bind(local_area, "<Leave>", lambda e: self.leave_variation(goban,grid,markup)) | |
self.current_variation_goban=goban | |
self.current_variation_grid=grid | |
self.current_variation_markup=markup | |
self.current_variation_i=i | |
self.current_variation_j=j | |
self.current_variation_move=move | |
self.current_variation_sequence=sequence | |
self.parent.bind("<Up>", self.show_variation_next) | |
self.parent.bind("<Down>", self.show_variation_prev) | |
self.parent.bind("<MouseWheel>", self.mouse_wheel) | |
if not self.inverted_mouse_wheel: | |
goban.tag_bind(local_area,"<Button-4>", self.show_variation_next) | |
goban.tag_bind(local_area,"<Button-5>", self.show_variation_prev) | |
else: | |
goban.tag_bind(local_area,"<Button-5>", self.show_variation_next) | |
goban.tag_bind(local_area,"<Button-4>", self.show_variation_prev) | |
self.set_status(_("Use mouse wheel or keyboard up/down keys to display the sequence move by move.")) | |
def mouse_wheel(self,event): | |
if self.current_variation_sequence==None: | |
return | |
d = event.delta | |
if self.inverted_mouse_wheel: | |
d*=-1 | |
if d>0: | |
self.show_variation_next() | |
elif d<0: | |
self.show_variation_prev() | |
def show_variation_next(self,event=None): | |
move=(self.current_variation_move+1)%(len(self.current_variation_sequence)+1) | |
move=max(1,move) | |
#log(move,'/',len(self.current_variation_sequence)) | |
self.show_variation_move(self.current_variation_goban,self.current_variation_grid,self.current_variation_markup,self.current_variation_i,self.current_variation_j,move) | |
def show_variation_prev(self,event=None): | |
move=(self.current_variation_move-1)%len(self.current_variation_sequence) | |
if move<1: | |
move=len(self.current_variation_sequence) | |
self.show_variation_move(self.current_variation_goban,self.current_variation_grid,self.current_variation_markup,self.current_variation_i,self.current_variation_j,move) | |
def show_territories(self,event=None): | |
black_t=self.territories[0] | |
white_t=self.territories[1] | |
dim=self.dim | |
markup=[["" for row in range(dim)] for col in range(dim)] | |
for i,j in black_t: | |
markup[i][j]=-1 | |
for i,j in white_t: | |
markup[i][j]=-2 | |
self.goban1.display(self.current_grid,markup) | |
def prepare_data_for_chart(self): | |
data=[] | |
for m in range(0,self.nb_moves+1): | |
one_data={} | |
data.append(one_data) | |
one_move=get_node(self.gameroot,m) | |
try: | |
player_color,player_move=one_move.get_move() | |
one_data['player_color']=player_color.lower() #which turn it is to play | |
except: | |
pass | |
try: | |
player_move=ij2gtp(player_move) | |
one_data['move']=m #move number | |
except: | |
pass | |
try: | |
es=one_move.get('ES') | |
if es[0]=="B": | |
one_data['score_estimation']=float(es[1:]) | |
else: | |
one_data['score_estimation']=-float(es[1:]) | |
one_data['lower_bound_score']=one_data['score_estimation'] | |
one_data['upper_bound_score']=one_data['score_estimation'] | |
except: | |
pass | |
try: | |
ubs=one_move.get('UBS') | |
if ubs[0]=="B": | |
one_data['upper_bound_score']=float(ubs[1:]) | |
else: | |
one_data['upper_bound_score']=-float(ubs[1:]) | |
except: | |
pass | |
try: | |
lbs=one_move.get('LBS') | |
if lbs[0]=="B": | |
one_data['lower_bound_score']=float(lbs[1:]) | |
else: | |
one_data['lower_bound_score']=-float(lbs[1:]) | |
except: | |
pass | |
try: | |
winrate=one_move.get('MCWR') | |
if player_color in ('b',"B"): | |
one_data['monte_carlo_win_rate']=float(winrate.split("%")[0]) | |
else: | |
one_data['monte_carlo_win_rate']=float(winrate.split("/")[1][:-1]) | |
except: | |
pass | |
try: | |
winrate=one_move.get('VNWR') | |
if player_color in ('b',"B"): | |
one_data['value_network_win_rate']=float(winrate.split("%")[0]) | |
else: | |
one_data['value_network_win_rate']=float(winrate.split("/")[1][:-1]) | |
except: | |
pass | |
#position win rate is the win rate for the position right before the player plays his move | |
#so it is the win rate of the best move by the computer for this position | |
#because we consider the bot plays perfectly | |
try: | |
winrate=one_move.get('BWWR') | |
if player_color in ('w',"W"): | |
current_position_win_rate=float(winrate.split("/")[1][:-1]) | |
else: | |
current_position_win_rate=float(winrate.split("%")[0]) | |
one_data['position_win_rate']=current_position_win_rate | |
except: | |
pass | |
#delta is the [position win rate of the next move] - [position win rate of the current move] | |
#so it allows to compare how the game would evolve from that position: | |
# 1/ in the case the computer best move is played (current_position_win_rate) | |
# 2/ compared with when the actual game move was played (next_position_win_rate) | |
# positive delta means the game evolves better when the actual game move is played | |
# negative delta means the game evolves better when the computer move is played | |
try: | |
next_move=get_node(self.gameroot,m+1) | |
winrate=next_move.get('BWWR') | |
if player_color in ('w',"W"): | |
next_position_win_rate=float(winrate.split("/")[1][:-1]) | |
else: | |
next_position_win_rate=float(winrate.split("%")[0]) | |
computer_move=one_move.get('CBM') | |
if player_move==computer_move: | |
# in case the computer best move is the actual game move then: | |
# 1/ normally delta=0 | |
# 2/ let's update current_position_win_rate using next_position_win_rate because it is a better evaluation | |
current_position_win_rate=next_position_win_rate | |
one_data['position_win_rate']=next_position_win_rate | |
delta=next_position_win_rate-one_data['position_win_rate'] #this will fail if the calculation of current_position_win_rate above failed, this is what we want | |
one_data['winrate_delta']=delta | |
except: | |
pass | |
#delta for monte carlo win rate | |
try: | |
next_move=get_node(self.gameroot,m+1) | |
winrate=next_move.get('MCWR') | |
if player_color in ('w',"W"): | |
next_position_win_rate=float(winrate.split("/")[1][:-1]) | |
else: | |
next_position_win_rate=float(winrate.split("%")[0]) | |
computer_move=one_move.get('CBM') | |
if player_move==computer_move: | |
current_position_win_rate=next_position_win_rate | |
one_data['monte_carlo_win_rate']=next_position_win_rate | |
delta=next_position_win_rate-one_data['monte_carlo_win_rate'] | |
one_data['mcwr_delta']=delta | |
except: | |
pass | |
#delta for value network win rate | |
try: | |
next_move=get_node(self.gameroot,m+1) | |
winrate=next_move.get('VNWR') | |
if player_color in ('w',"W"): | |
next_position_win_rate=float(winrate.split("/")[1][:-1]) | |
else: | |
next_position_win_rate=float(winrate.split("%")[0]) | |
computer_move=one_move.get('CBM') | |
if player_move==computer_move: | |
current_position_win_rate=next_position_win_rate | |
one_data['value_network_win_rate']=next_position_win_rate | |
delta=next_position_win_rate-one_data['value_network_win_rate'] | |
one_data['vnwr_delta']=delta | |
except: | |
pass | |
if len(one_data)<=2: | |
#if move number and color are the only data available for this point | |
#then we don't need that data point | |
data.pop() | |
return data | |
def show_graphs(self,event=None): | |
new_popup=OpenChart(self,self.data_for_chart,self.nb_moves) | |
new_popup.current_move=self.current_move | |
self.all_popups.append(new_popup) | |
def hide_territories(self,event=None): | |
self.goban1.display(self.current_grid,self.current_markup) | |
def display_move(self,move=1): | |
dim=self.dim | |
goban1=self.goban1 | |
goban2=self.goban2 | |
self.move_number.config(text=str(move)+'/'+str(self.nb_moves)) | |
log("========================") | |
log("displaying move",move) | |
grid1=[[0 for row in range(dim)] for col in range(dim)] | |
markup1=[["" for row in range(dim)] for col in range(dim)] | |
grid2=[[0 for row in range(dim)] for col in range(dim)] | |
markup2=[["" for row in range(dim)] for col in range(dim)] | |
board, noneed = sgf_moves.get_setup_and_moves(self.sgf) | |
self.current_grid=grid1 | |
self.current_markup=markup1 | |
for colour, move0 in board.list_occupied_points(): | |
if move0 is None: | |
continue | |
row, col = move0 | |
if colour=='b': | |
place(grid1,row,col,1) | |
place(grid2,row,col,1) | |
else: | |
place(grid1,row,col,2) | |
place(grid2,row,col,2) | |
m=0 | |
for m in range(1,move): | |
one_move=get_node(self.gameroot,m) | |
if one_move==False: | |
log("(2)leaving because one_move==False") | |
return | |
ij=one_move.get_move()[1] | |
if ij==None: | |
log("(3)skipping because ij==None",ij) | |
continue | |
if one_move.get_move()[0]=='b':color=1 | |
else:color=2 | |
i,j=list(ij) | |
place(grid1,i,j,color) | |
place(grid2,i,j,color) | |
if len(one_move)==0: | |
log("(4)leaving because len(one_move)==0") | |
goban1.display(grid1,markup1) | |
goban2.display(grid2,markup2) | |
return | |
self.territories=[[],[]] | |
if m>0: | |
the_move=one_move | |
if one_move.has_property("TB"): | |
self.territories[0]=one_move.get("TB") | |
if one_move.has_property("TW"): | |
self.territories[1]=one_move.get("TW") | |
if self.territories!=[[],[]]: | |
self.territory_button.grid() | |
else: | |
self.territory_button.grid_remove() | |
#indicating last play with delta | |
self.comment_box1.delete(1.0, END) | |
"""if m>=0: | |
if get_node(self.gameroot,m+1).has_property("C"): | |
self.comment_box1.insert(END,get_node(self.gameroot,m+1).get("C")) | |
""" | |
if m>=0: | |
left_comments=self.get_node_comments() | |
if get_node(self.gameroot,m+1).has_property("C"): | |
left_comments+="\n"+get_node(self.gameroot,m+1).get("C") | |
self.comment_box1.insert(END,left_comments) | |
if m>0: | |
markup1[i][j]=0 | |
markup2[i][j]=0 | |
self.comment_box2.delete(1.0, END) | |
#next sequence in current game ############################################################################ | |
main_sequence=[] | |
for m in range(self.realgamedeepness): | |
one_move=get_node(self.gameroot,move+m) | |
if one_move==False: | |
log("(5)leaving because one_move==False") | |
break | |
ij=one_move.get_move()[1] | |
if ij==None: | |
log("(6)skipping because ij==None",ij) | |
break | |
if one_move.get_move()[0]=='b': c=1 | |
else: c=2 | |
main_sequence.append([c,ij,"A",None,"black","black"]) | |
if m==0: | |
real_game_ij=ij | |
try: | |
i,j=list(get_node(self.gameroot,move).get_move()[1]) | |
except: | |
self.prev_move() | |
return | |
if main_sequence: | |
markup1[i][j]=main_sequence | |
else: | |
real_game_ij=(-1,-1) | |
#real_game_ij=get_node(self.gameroot,move).get_move()[1] | |
#alternative sequences #################################################################################### | |
parent=get_node(self.gameroot,move-1) | |
if parent==False: | |
log("(7)leaving because one_move==False") | |
return | |
if len(parent)<=1: | |
log("no alternative move") | |
goban1.display(grid1,markup1) | |
goban2.display(grid2,markup2) | |
self.table_button.config(state='disabled') | |
return | |
else: | |
self.table_button.config(state='normal') | |
for a in range(1,min(len(parent),self.maxvariations+1)): | |
one_alternative=parent[a] | |
ij=one_alternative.get_move()[1] | |
displaycolor='black' | |
if one_alternative.get_move()[0]=='b': c=1 | |
else: c=2 | |
if one_alternative.has_property("BWWR"): | |
black_prob=float(one_alternative.get("BWWR").split("%")[0]) | |
white_prob=100-black_prob | |
if c==1: | |
if self.variation_color_mode=="blue_for_winning": | |
if black_prob>=50: | |
displaycolor="blue" | |
else: | |
displaycolor="red" | |
elif self.variation_color_mode=="blue_for_best": | |
if a==1: | |
displaycolor="blue" | |
else: | |
displaycolor="red" | |
elif self.variation_color_mode=="blue_for_better": | |
try: | |
real_game_prob=float(the_move[0][0].get("BWR")[:-1]) | |
if real_game_prob<black_prob: | |
displaycolor="blue" | |
elif real_game_prob>black_prob: | |
displaycolor="red" | |
except: | |
pass | |
else: | |
if self.variation_color_mode=="blue_for_winning": | |
if black_prob>50: | |
displaycolor="red" | |
else: | |
displaycolor="blue" | |
elif self.variation_color_mode=="blue_for_best": | |
if a==1: | |
displaycolor="blue" | |
else: | |
displaycolor="red" | |
elif self.variation_color_mode=="blue_for_better": | |
try: | |
real_game_prob=float(the_move[0][0].get("WWR")[:-1]) | |
if real_game_prob<white_prob: | |
displaycolor="blue" | |
elif real_game_prob>white_prob: | |
displaycolor="red" | |
except: | |
pass | |
comment='' | |
for sgf_property in ("BWWR","PNV","MCWR","VNWR","PLYO","EVAL","RAVE","ES"): | |
if one_alternative.has_property(sgf_property): | |
comment+=format_data(sgf_property,variation_data_formating,one_alternative.get(sgf_property))+"\n" | |
if one_alternative.has_property("C"): | |
comment+=one_alternative.get("C") | |
if ij==real_game_ij: | |
letter_color="black" | |
else: | |
letter_color=displaycolor | |
alternative_sequence=[[c,ij,chr(64+a),comment,displaycolor,letter_color]] | |
while len(one_alternative)>0: | |
one_alternative=one_alternative[0] | |
ij=one_alternative.get_move()[1] | |
if one_alternative.get_move()[0]=='b':c=1 | |
else:c=2 | |
alternative_sequence.append([c,ij,chr(64+a),comment,"whocare?","whocare"]) | |
i,j=parent[a].get_move()[1] | |
markup2[i][j]=alternative_sequence | |
goban1.display(grid1,markup1) | |
goban2.display(grid2,markup2) | |
def open_move(self): | |
log("Opening move",self.current_move) | |
new_popup=OpenMove(self,self.current_move,self.dim,self.sgf,self.goban_size) | |
new_popup.goban.mesh=self.goban1.mesh | |
new_popup.goban.wood=self.goban1.wood | |
new_popup.goban.black_stones=self.goban1.black_stones | |
new_popup.goban.white_stones=self.goban1.white_stones | |
new_popup.goban.no_redraw=[] | |
new_popup.goban.display(new_popup.grid,new_popup.markup) | |
self.all_popups.append(new_popup) | |
def get_node_comments(self): | |
comments="" | |
if self.current_move==1: | |
if self.gameroot.has_property("RSGF"): | |
comments+=self.gameroot.get("RSGF") | |
if self.gameroot.has_property("PB"): | |
comments+=_("Black")+": "+self.gameroot.get("PB")+"\n" | |
if self.gameroot.has_property("PW"): | |
comments+=_("White")+": "+self.gameroot.get("PW")+"\n" | |
comments+="\n"+_("Move %i")%self.current_move | |
game_move_color,game_move=get_node(self.gameroot,self.current_move).get_move() | |
if game_move_color.lower()=="w": | |
comments+="\n"+(position_data_formating["W"])%ij2gtp(game_move) | |
elif game_move_color.lower()=="b": | |
comments+="\n"+(position_data_formating["B"])%ij2gtp(game_move) | |
node=get_node(self.gameroot,self.current_move) | |
if node.has_property("CBM"): | |
if self.gameroot.has_property("BOT"): | |
bot=self.gameroot.get("BOT") | |
else: | |
bot=_("the computer") | |
comments+="\n"+(position_data_formating["CBM"])%(bot,node.get("CBM")) | |
try: | |
if node[1].has_property("BKMV"): | |
if node[1].get("BKMV")=="yes": | |
comments+=" ("+variation_data_formating["BKMV"]+")" | |
except: | |
pass | |
try: | |
if node.has_property("BWWR"): | |
if node[0].has_property("BWWR"): | |
if node.get_move()[0].lower()=="b": | |
comments+="\n\n"+_("Black win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("BWWR").split("/")[0] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("BWWR").split("/")[0] | |
comments+=" (%+.2fpp)"%(float(node[0].get("BWWR").split("%/")[0])-float(node.get("BWWR").split("%/")[0])) | |
else: | |
comments+="\n\n"+_("White win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("BWWR").split("/")[1] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("BWWR").split("/")[1] | |
comments+=" (%+.2fpp)"%(float(node[0].get("BWWR").split("%/")[1][:-1])-float(node.get("BWWR").split("%/")[1][:-1])) | |
except: | |
pass | |
try: | |
if node.has_property("VNWR"): | |
if node[0].has_property("VNWR"): | |
if node.get_move()[0].lower()=="b": | |
comments+="\n\n"+_("Black Value Network win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("VNWR").split("/")[0] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("VNWR").split("/")[0] | |
comments+=" (%+.2fpp)"%(float(node[0].get("VNWR").split("%/")[0])-float(node.get("VNWR").split("%/")[0])) | |
else: | |
comments+="\n\n"+_("White Value Network win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("VNWR").split("/")[1] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("VNWR").split("/")[1] | |
comments+=" (%+.2fpp)"%(float(node[0].get("VNWR").split("%/")[1][:-1])-float(node.get("VNWR").split("%/")[1][:-1])) | |
except: | |
pass | |
try: | |
if node.has_property("MCWR"): | |
if node[0].has_property("MCWR"): | |
if node.get_move()[0].lower()=="b": | |
comments+="\n\n"+_("Black Monte Carlo win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("MCWR").split("/")[0] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("MCWR").split("/")[0] | |
comments+=" (%+.2fpp)"%(float(node[0].get("MCWR").split("%/")[0])-float(node.get("MCWR").split("%/")[0])) | |
else: | |
comments+="\n\n"+_("White Monte Carlo win probability:") | |
comments+="\n • "+(_("before %s")%ij2gtp(game_move))+": "+node.get("MCWR").split("/")[1] | |
comments+="\n • "+(_("after %s")%ij2gtp(game_move))+": "+node[0].get("MCWR").split("/")[1] | |
comments+=" (%+.2fpp)"%(float(node[0].get("MCWR").split("%/")[1][:-1])-float(node.get("MCWR").split("%/")[1][:-1])) | |
except: | |
pass | |
return comments | |
def open_table(self): | |
log("opening table") | |
new_popup=Toplevel(self.parent) | |
Label(new_popup,text=" ").grid(row=0,column=0) | |
Label(new_popup,text=" ").grid(row=1000,column=1000) | |
row=1 | |
comments=self.get_node_comments() | |
Label(new_popup,text=comments,justify=LEFT).grid(row=row,column=1,columnspan=100,sticky=W) | |
Label(new_popup,text=" ").grid(row=row+1,column=0) | |
columns_header=[_("Move"),'nothing here',_("Win rate"),_("Monte Carlo win rate"),_("Value Network win rate"),_("Policy Network value"),_("Playouts"),_("Evaluation"),_("RAVE"),_("Score estimation")] | |
columns_sgf_properties=["nothing here","nothing here","BWWR","MCWR","VNWR","PNV","PLYO","EVAL","RAVE","ES"] | |
parent=get_node(self.gameroot,self.current_move-1) | |
nb_variations=min(len(parent)-1,self.maxvariations+1) | |
log(nb_variations,"variations") | |
columns=[[None for i in range(nb_variations+1)] for j in range(len(columns_header))] | |
for a in range(1,min(len(parent),self.maxvariations+1)): | |
one_alternative=parent[a] | |
c=0 | |
for key in columns_sgf_properties: | |
if one_alternative.has_property(key): | |
value=one_alternative.get(key) | |
if "%/" in value: | |
if parent[0].get_move()[0].lower()=="b": | |
value=value.split("/")[0] | |
else: | |
value=value.split("/")[1] | |
columns[c][a]=value | |
c+=1 | |
columns[0][a]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[a-1] | |
columns[1][a]=ij2gtp(one_alternative.get_move()[1]) | |
try: | |
columns[0][0]="A" | |
columns[1][0]=ij2gtp(parent[0].get_move()[1]) | |
one_alternative=parent[0][1] | |
c=0 | |
for key in columns_sgf_properties: | |
if one_alternative.has_property(key): | |
value=one_alternative.get(key) | |
if "%/" in value: | |
if parent[0].get_move()[0].lower()=="b": | |
value=value.split("/")[0] | |
else: | |
value=value.split("/")[1] | |
columns[c][0]=value | |
c+=1 | |
except: | |
pass | |
c=0 | |
for column in columns: | |
empty=True | |
for row in column: | |
if row!=None: | |
empty=False | |
break | |
if empty: | |
columns_header[c]=None | |
c+=1 | |
row=10 | |
c=0 | |
for header in columns_header: | |
if header: | |
if c==0: | |
Label(new_popup,text=header,relief=SUNKEN).grid(row=row,column=10+c,columnspan=2,sticky=W+E) | |
elif c==1: | |
pass | |
else: | |
Label(new_popup,text=header,relief=SUNKEN).grid(row=row,column=10+c,sticky=W+E) | |
c+=1 | |
row+=1 | |
for c in range(len(columns)): | |
for r in range(nb_variations): | |
if columns_header[c]: | |
Label(new_popup,text=columns[c][r],relief=SUNKEN).grid(row=row+r,column=10+c,sticky=W+E) | |
def initialize(self): | |
self.realgamedeepness=5 | |
try: | |
self.realgamedeepness=int(Config.get("Review", "RealGameSequenceDeepness")) | |
except: | |
Config.set("Review", "RealGameSequenceDeepness",self.realgamedeepness) | |
Config.write(open(config_file,"w")) | |
self.maxvariations=10 | |
try: | |
self.maxvariations=int(Config.get("Review", "MaxVariations")) | |
except: | |
Config.set("Review", "MaxVariations",self.maxvariations) | |
Config.write(open(config_file,"w")) | |
self.sgf = open_sgf(self.filename) | |
self.dim=self.sgf.get_size() | |
self.komi=self.sgf.get_komi() | |
log("boardsize:",self.dim) | |
#goban.dim=size | |
#goban.prepare_mesh() | |
self.gameroot=self.sgf.get_root() | |
self.nb_moves=get_node_number(self.gameroot) | |
for m in range(0,self.nb_moves+1)[::-1]: | |
one_move=get_node(self.gameroot,m) | |
player_color,player_move=one_move.get_move() | |
if (player_color==None) or (player_move==None): | |
self.nb_moves-=1 | |
else: | |
break | |
self.data_for_chart=self.prepare_data_for_chart() | |
self.parent.title('GoReviewPartner') | |
self.parent.protocol("WM_DELETE_WINDOW", self.close_app) | |
self.all_popups=[] | |
bg=self.cget("background") | |
#self.configure(background=bg) | |
# Such frames | |
buttons_bar=Frame(self,background=bg) | |
buttons_bar2=Frame(self,background=bg) | |
lists_frame=Frame(self,background=bg) | |
#Create widgets for main window | |
#self.goban1 = Canvas(self, width=10, height=10,bg=bg,bd=0, borderwidth=0) | |
self.goban1 = Goban(self.dim,master=self, width=10, height=10,bg=bg,bd=0, borderwidth=0) #bg | |
#self.goban2 = Canvas(self, width=10, height=10,bg=bg,bd=0, borderwidth=0) | |
self.goban2 = Goban(self.dim, master=self, width=10, height=10,bg=bg,bd=0, borderwidth=0) | |
self.goban2.mesh=self.goban1.mesh | |
self.goban2.wood=self.goban1.wood | |
self.goban2.black_stones=self.goban1.black_stones | |
self.goban2.white_stones=self.goban1.white_stones | |
self.goban1.space=self.goban_size/(self.dim+1+1) | |
self.goban2.space=self.goban_size/(self.dim+1+1) | |
self.status_bar=Label(self,text='',background=bg, wraplength = self.goban_size - 2) | |
#Create widgets for the buttons_bar - game navigation | |
first_move_button=Button(buttons_bar, text='|<< ',command=self.first_move) | |
prev_10_moves_button=Button(buttons_bar, text=' << ',command=self.prev_10_move) | |
prev_button=Button(buttons_bar, text=' < ',command=self.prev_move) | |
self.move_number=Label(buttons_bar,text=' ',background=bg) | |
next_button=Button(buttons_bar, text=' > ',command=self.next_move) | |
next_10_moves_button=Button(buttons_bar, text=' >> ',command=self.next_10_move) | |
final_move_button=Button(buttons_bar, text=' >>|',command=self.final_move) | |
#Create widgets for the buttons_bar2 - commands and extra windows | |
open_button=Button(buttons_bar2, text=_('Open position'),command=self.open_move) | |
self.territory_button=Button(buttons_bar2, text=_('Show territories')) | |
self.table_button=Button(buttons_bar2,text=_("Table"),command=self.open_table) | |
for data in self.data_for_chart: | |
if data<>None: | |
self.charts_button=Button(buttons_bar2, text=_('Graphs')) | |
break | |
#Create widgets for the rightmost list frame | |
police = tkFont.nametofont("TkFixedFont") | |
lpix = police.measure("a") | |
self.lpix=lpix | |
self.comment_lines = int(self.goban_size / 2 / police.metrics('linespace') - 2) | |
self.comment_chars = 30 | |
self.comment_box1=ScrolledText(lists_frame,font=police,wrap="word",height=self.comment_lines,width=self.comment_chars,foreground='black') | |
self.comment_box2=ScrolledText(lists_frame,font=police,wrap="word",height=self.comment_lines,width=self.comment_chars,foreground='black') | |
#Place widgets in button_bar | |
first_move_button.grid(column=8,row=1) | |
prev_10_moves_button.grid(column=9,row=1) | |
prev_button.grid(column=10,row=1) | |
Label(buttons_bar,text=' ',background=bg).grid(column=19,row=1) | |
self.move_number.grid(column=20,row=1) | |
Label(buttons_bar,text=' ',background=bg).grid(column=29,row=1) | |
next_button.grid(column=30,row=1) | |
next_10_moves_button.grid(column=31,row=1) | |
final_move_button.grid(column=32,row=1) | |
#Place widgets in command bar | |
open_button.grid(column=1,row=1) | |
self.table_button.grid(column=2,row=1) | |
if self.charts_button <> None: | |
self.charts_button.grid(column=3,row=1) #,sticky=E | |
self.territory_button.grid(column=4,row=1) | |
#Place widgets in lists frame | |
self.comment_box1.grid(column=1,row=1,sticky=N+S+E+W, padx=2, pady=2) | |
self.comment_box2.grid(column=1,row=2,sticky=N+S+E+W, padx=2, pady=2) | |
lists_frame.grid_columnconfigure(1, weight=1) | |
lists_frame.grid_rowconfigure(1, weight=1) | |
lists_frame.grid_rowconfigure(2, weight=1) | |
#Place widgets in main frame | |
self.goban1.grid(column=1,row=1,sticky=W+E+N+S) | |
Label(self, text=' ',background=bg).grid(column=2,row=1) | |
self.goban2.grid(column=3,row=1,sticky=W+E+N+S) | |
self.status_bar.grid(column=1,row=2,sticky=W) | |
buttons_bar.grid(column=3,row=2,sticky=S,pady=5) | |
lists_frame.grid(column=5,row=0,rowspan=2,sticky=N+S+E+W,pady=5) | |
buttons_bar2.grid(column=5,row=2,sticky=S,pady=5) #,sticky=W | |
self.grid_columnconfigure(1, weight=1) | |
self.grid_columnconfigure(3, weight=1) | |
self.grid_columnconfigure(5, weight=1) | |
self.grid_rowconfigure(1, weight=1) | |
#self.grid_columnconfigure(5, weight=1) | |
#Label(app,background=bg).grid(column=1,row=2) | |
#Label(self,background=bg).grid(column=1,row=row-1) | |
#self.grid_rowconfigure(1, weight=1) | |
#self.grid_columnconfigure(1, weight=1) | |
#self.grid_columnconfigure(3, weight=1) | |
#Label(self,text=' ',background=bg).grid(column=4,row=row+1) | |
#Label(self,text=' ',background=bg).grid(column=4,row=row+6) | |
# Keybindings | |
self.territory_button.bind('<Button-1>', self.show_territories) | |
self.territory_button.bind('<ButtonRelease-1>', self.hide_territories) | |
self.parent.bind('<Control-q>', self.save_left_as_png) | |
self.parent.bind('<Control-w>', self.save_right_as_png) | |
self.parent.bind('<Left>', self.prev_move) | |
self.parent.bind('<Right>', self.next_move) | |
if self.charts_button <> None: | |
self.charts_button.bind('<Button-1>', self.show_graphs) | |
# Tooltips | |
first_move_button.bind("<Enter>",lambda e: self.set_status(_("Go to first move."))) | |
prev_10_moves_button.bind("<Enter>",lambda e: self.set_status(_("Go back 10 moves."))) | |
prev_button.bind("<Enter>",lambda e: self.set_status(_("Go back one move. Shortcut: keyboard left key."))) | |
open_button.bind("<Enter>",lambda e: self.set_status(_("Open this position onto a third goban to play out variations."))) | |
next_button.bind("<Enter>",lambda e: self.set_status(_("Go forward one move. Shortcut: keyboard right key."))) | |
next_10_moves_button.bind("<Enter>",lambda e: self.set_status(_("Go forward 10 moves."))) | |
final_move_button.bind("<Enter>",lambda e: self.set_status(_("Go to final move."))) | |
self.territory_button.bind("<Enter>",lambda e: self.set_status(_("Keep pressed to show territories."))) | |
self.goban1.bind("<Enter>",lambda e: self.set_status(_("<Ctrl+Q> to save the goban as an image."))) | |
self.goban2.bind("<Enter>",lambda e: self.set_status(_("<Ctrl+W> to save the goban as an image."))) | |
for button in [first_move_button,prev_10_moves_button,prev_button,open_button,next_button,next_10_moves_button,final_move_button,self.territory_button,self.goban1,self.goban2]: | |
button.bind("<Leave>",lambda e: self.clear_status()) | |
self.goban1.bind("<Configure>",self.redraw) | |
goban.show_variation=self.show_variation | |
def redraw(self, event): | |
new_size=min(event.width,event.height) | |
new_space=new_size/(self.dim+1+1) | |
self.goban1.space=new_space | |
self.goban2.space=new_space | |
new_anchor_x=(event.width-new_size)/2 | |
self.goban1.anchor_x=new_anchor_x | |
self.goban2.anchor_x=new_anchor_x | |
new_anchor_y=(event.height-new_size)/2 | |
self.goban1.anchor_y=new_anchor_y | |
self.goban2.anchor_y=new_anchor_y | |
self.goban1.redraw() | |
self.goban2.redraw() | |
if sys.platform!="darwin": | |
# #https://github.com/pnprog/goreviewpartner/issues/7 | |
self.comment_box1.config(width=self.comment_chars) | |
self.comment_box2.config(width=self.comment_chars) | |
def set_status(self,msg): | |
self.status_bar.config(text=msg) | |
def clear_status(self): | |
self.status_bar.config(text="") | |
def save_left_as_png(self,e=None): | |
filename = save_png_file(parent=self.parent,filename='move'+str(self.current_move)+'.png') | |
canvas2png(self.goban1,filename) | |
def save_right_as_png(self,e=None): | |
filename = save_png_file(parent=self.parent,filename='move'+str(self.current_move)+'.png') | |
canvas2png(self.goban2,filename) | |
def canvas2png(goban,filename): | |
top = goban.winfo_rooty() | |
left = goban.winfo_rootx() | |
width = goban.winfo_width() | |
height = goban.winfo_height() | |
monitor = {'top': top, 'left': left, 'width': width, 'height': height} | |
sct_img = mss.mss().grab(monitor) | |
mss.tools.to_png(sct_img.rgb, sct_img.size, output=filename) | |
from gomill import sgf, sgf_moves | |
import goban | |
#goban.fuzzy=float(Config.get("Review", "FuzzyStonePlacement")) | |
if __name__ == "__main__": | |
Config = ConfigParser.ConfigParser() | |
Config.read(config_file) | |
if len(sys.argv)==1: | |
temp_root = Tk() | |
filename = open_rsgf_file(parent=temp_root) | |
temp_root.destroy() | |
log(filename) | |
if not filename: | |
sys.exit() | |
else: | |
filename=sys.argv[1] | |
top = Tk() | |
display_factor=.5 | |
try: | |
display_factor=float(Config.get("Review", "GobanScreenRatio")) | |
except: | |
Config.set("Review", "GobanScreenRatio",display_factor) | |
Config.write(open(config_file,"w")) | |
screen_width = top.winfo_screenwidth() | |
screen_height = top.winfo_screenheight() | |
width=int(display_factor*screen_width) | |
height=int(display_factor*screen_height) | |
DualView(top,filename,min(width,height)).pack(fill=BOTH,expand=1) | |
top.mainloop() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment