diff --git a/src/diana.py b/src/diana.py
--- a/src/diana.py
+++ b/src/diana.py
@@ -3,11 +3,18 @@ import re
import sys
import go
-import sgf
+from go import BLACK,WHITE,EMPTY
+from sgfParser.collection import Collection
from drawer.svg import Svg
from drawer.tikz import Tikz
+
+templateDir=os.path.join(os.path.dirname(__file__),"templ")
+with open(os.path.join(templateDir,"templ.svg")) as f:
+ template=f.read()
+
+
if len(sys.argv)>1:
files=sys.argv[1:]
else:
@@ -19,14 +26,28 @@ minMovesPerDiagram=10
t=sys.stdout
+def collectMoves(root):
+ node=root
+ while len(node.children)>0:
+ b=node.getProp("B")
+ w=node.getProp("W")
+ if b is not None: yield ("b",b)
+ elif w is not None: yield ("w",w)
+ # else: yield None # !! not really robust
+
+ node=node.children[0]
+
+
def processFile(fileName):
shortName="".join(re.split(r'[/\\]',fileName)[-1].split('.')[:-1])
game=go.Go()
global t
-
- record=sgf.Sgf(open(fileName, 'r', encoding="utf-8").read())
- moves=record.getMoves()
+
+ games=Collection(open(fileName, 'r', encoding="utf-8").read()).listGames()
+ record=list(games)[0]
+
+ moves=list(collectMoves(record))
localBoard=dict()
overlays=""
@@ -37,52 +58,51 @@ def processFile(fileName):
moveNumber=0
for i in range(diagramsNeeded):
- # inicializuj diagram
- diagram=Tikz()
+ # initialize the diagram
+ diagram=Svg()
for lineNumber,line in enumerate(game.board):
for itemNumber,item in enumerate(line):
- if item==1: diagram.drawStone(itemNumber,lineNumber,"b")
- if item==-1: diagram.drawStone(itemNumber,lineNumber,"w")
- localBoard={(a,b):game.board[b][a]-1 for a in range(19) for b in range(19) if game.board[b][a]!=0}
+ if item==BLACK: diagram.addStone(itemNumber,lineNumber,"b")
+ if item==WHITE: diagram.addStone(itemNumber,lineNumber,"w")
+ localBoard={(a,b):game.board[b][a]-1 for a in range(19) for b in range(19) if game.board[b][a]!=EMPTY}
for j in range(movesPerDiagram):
- # kresli tahy
+ # draw the moves
if moveNumber>=len(moves): break
-
+
c,(x,y)=moves[moveNumber]
c=c.lower()
- if not game.move(1 if c=='b' else -1,x,y):
+ if not game.move(BLACK if c=='b' else WHITE, x,y):
print("illegal move: {0} at {1},{2}".format(moveNumber+1,x,y))
moveNumber+=1
continue
-
- # zapíšu tah na volný průsečík
+
+ # draw the move on an empty intersection
if not (x,y) in localBoard:
localBoard[(x,y)]=moveNumber+1
- diagram.drawMove(x,y,moveNumber+1,c)
- # průsečík je obsazený nepopsaným kamenem
+ diagram.addMove(x,y,c,moveNumber+1)
+ # intersection occupied by an unlabeled stone
elif localBoard[(x,y)]<1:
- # průsečík není popsaný ani písmenem
+ # intersection not labeled even by a letter
if not (x,y) in letters:
letters[(x,y)]=letter
- color='b' if localBoard[(x,y)]==0 else 'w'
- diagram.drawMove(x,y,letter,color)
+ color='b' if localBoard[(x,y)]==EMPTY else 'w'
+ diagram.addMove(x,y,color,letter)
letter=chr(ord(letter)+1)
overlays+="{0} = {1}\n".format(moveNumber+1,letters[(x,y)])
- # průsečík je obsazený očíslovaným kamenem
+ # intersection occupied by a numbered stone
else: overlays+="{0} = {1}\n".format(moveNumber+1,localBoard[(x,y)])
moveNumber+=1
- # dokonči a ulož diagram
- # TODO rozumně pracovat s adresáři
- t=open(os.path.join(os.path.dirname(__file__),"out","{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # nový soubor
- t.write(diagram.getContent())
+ # finish and save the diagram
+ t=open(os.path.join("out","{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # a new file
+ t.write(diagram.render(template))
t.close()
- notes=open(os.path.join(os.path.dirname(__file__),"out","{0}.txt".format(shortName)),'w')
+ notes=open(os.path.join("out","{0}.txt".format(shortName)),'w')
notes.write(overlays)
notes.close()
diff --git a/src/drawer/svg.py b/src/drawer/svg.py
old mode 100644
new mode 100755
--- a/src/drawer/svg.py
+++ b/src/drawer/svg.py
@@ -1,72 +1,64 @@
+from jinja2 import Template
+
+
c=28
padding=15
highNumbers=True
+class DiagramPoint:
+ def __init__(self,x,y,color="",label=""):
+ self.x=x
+ self.y=y
+ self.color=color
+ self.label=label
+
+ def __repr__(self):
+ return 'DiagramPoint({0},{1},"{2}","{3}")'.format(self.x,self.y,self.color,self.label)
+
+
class Svg:
- content=""
- footer=""
extension="svg"
padding=15
- gridSize=28
highNumbers=True
def __init__(self):
- self.content='''
-\n"
+ self.boardSize=480
+ self.padding=30
+
+ self._index=dict()
+
+ def addStone(self,x,y,color):
+ self._index[(x,y)]=(len(self._index),DiagramPoint(x,y,color))
- grid=' \n'
+ def addMove(self,x,y,color,label):
+ if (not self.highNumbers) and isinstance(label,int) and label%100!=0:
+ label%=100
- # okraje desky
- for i in (0,18):
- self.content+=' \n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding)
- self.content+=' \n'.format(self.gridSize*i+self.padding, self.gridSize*i+self.padding, self.padding, 18*self.gridSize+self.padding)
-
- # mřížka
- for i in range(1,18):
- self.content+=grid.format(self.padding, 18*self.gridSize+self.padding, c*i+self.padding, c*i+self.padding)
- self.content+=grid.format(c*i+self.padding, c*i+self.padding, self.padding, 18*c+self.padding)
+ self._index[(x,y)]=(len(self._index),DiagramPoint(x,y,color,label))
+
+ def addLabel(self,x,y,label):
+ self._index[(x,y)]=(len(self._index),DiagramPoint(x,y,"",label))
- # hvězdy
- for i in range(3):
- for j in range(3):
- self.content+=' \n'.format(padding+3*c+6*i*c, padding+3*c+6*j*c, 2)
-
- def __str__(self):
- return self.content+self.footer
-
- def drawStone(self,x,y,color):
- self.content+=' \n'.format(padding+x*c, padding+y*c, c/2-1, color)
+ def render(self, template):
+ points = [p for (i,p) in sorted(self._index.values())]
- def getFontSize(self,text):
- if len(text)<2: return round(0.7*c)
- elif len(text)<3: return round(0.55*c)
- else: return round(0.4*c)
+ stones = [p for p in points if p.color and not p.label]
+ moves = [p for p in points if p.color and p.label]
+ labels = [p for p in points if not p.color and p.label]
+
+ svg = Template(template)
+ params = {"boardSize":self.boardSize, "padding":self.padding, "stones":stones, "moves":moves, "labels":labels}
- def writeLabel(self,x,y,label,color):
- label=str(label)
- fontSize=self.getFontSize(label)
- self.content+=' {4}\n'.format(padding+x*c, padding+y*c+0.35*fontSize, color, fontSize, label)
-
- def drawMove(self,x,y,label,color):
- labelColor="w" if color=="b" else "b"
-
- if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
-
- self.drawStone(x,y,color)
- self.writeLabel(x,y,label,labelColor)
-
- def getContent(self):
- return self.content+self.footer
+ return svg.render(params)
+
+ # def getFontSize(self,text):
+ # if len(text)<2: return round(0.7*c)
+ # elif len(text)<3: return round(0.55*c)
+ # else: return round(0.4*c)
+ #
+ # def writeLabel(self,x,y,label,color):
+ # label=str(label)
+ # fontSize=self.getFontSize(label)
+ # self.content+=' {4}\n'.format(padding+x*c, padding+y*c+0.35*fontSize, color, fontSize, label)
diff --git a/src/go.py b/src/go.py
--- a/src/go.py
+++ b/src/go.py
@@ -1,12 +1,15 @@
-class Go:
- # 1: B, 0: _, -1: W
- # resp. jakákoli čísla s opačnými znaménky
- board=[[0]*19 for i in range(19)]
+BLACK=1
+WHITE=-1
+EMPTY=0
+
+
+class Go:
+ board=[[EMPTY]*19 for i in range(19)]
- def __init__(self): self.board=[[0]*19 for i in range(19)]
+ def __init__(self): self.board=[[EMPTY]*19 for i in range(19)]
def move(self,color,y,x):
- if self.board[x][y]!=0: return False
+ if self.board[x][y]!=EMPTY: return False
self.board[x][y]=color
@@ -15,14 +18,14 @@
if not self._floodFill(-color,x+i,y+j): self._remove()
self.temp=[[False]*19 for i in range(19)]
if not self._floodFill(color,x,y):
- self.board[x][y]=0
+ self.board[x][y]=EMPTY
return False
return True
def _floodFill(self,color,x,y):
if x<0 or x>18 or y<0 or y>18: return False
if self.temp[x][y]: return False
- if self.board[x][y]==0: return True
+ if self.board[x][y]==EMPTY: return True
if self.board[x][y]!=color: return False
self.temp[x][y]=True
return self._floodFill(color,x-1,y) or self._floodFill(color,x+1,y) or self._floodFill(color,x,y-1) or self._floodFill(color,x,y+1)
@@ -30,4 +33,4 @@
def _remove(self):
for i in range(19):
for j in range(19):
- if self.temp[i][j]: self.board[i][j]=0
+ if self.temp[i][j]: self.board[i][j]=EMPTY
diff --git a/src/sgfParser/node.py b/src/sgfParser/node.py
--- a/src/sgfParser/node.py
+++ b/src/sgfParser/node.py
@@ -67,8 +67,8 @@ class Node:
res.setChildren(self.children[:])
return res
- def getProperty(self,name):
- if name in self.properties: return self.properties[name]
+ def getProp(self,name):
+ if name in self.properties: return self.properties[name].value
else: return None
## Returns textual representation of the Node itself, but disregards its children.
diff --git a/src/templ/templ.svg b/src/templ/templ.svg
new file mode 100755
--- /dev/null
+++ b/src/templ/templ.svg
@@ -0,0 +1,53 @@
+
+{% set cellSize=boardSize/18 %}
+{% set stoneRadius=cellSize/2-1 %}
+
+