Files @ a362783e3bec
Branch filter:

Location: Diana/src/diana.py

Laman
exporting SGF back to string, also useful Composed and Point property classes
import os
import re
import sys

import go
import sgf

if len(sys.argv)>1:
	files=sys.argv[1:]
else:
	sys.exit("no input file specified")

movesPerDiagram=75
minMovesPerDiagram=10

t=sys.stdout
c=28
padding=15
highNumbers=True

class Svg:
	content=""
	footer=""
	extension="svg"

	padding=15
	gridSize=28
	highNumbers=True
	
	def __init__(self):
		self.content='''<?xml version="1.0" standalone="no"?>
<svg width="{0}" height="{0}" version="1.1" xmlns="http://www.w3.org/2000/svg" alignment-baseline="center">
	<defs>
		<style type="text/css"><![CDATA[
		text{{font-family:"DejaVu Sans";text-anchor:middle;}}
		line{{stroke:black;stroke-width:0.7}}
		circle{{stroke:black}}
		.b{{fill:black}}
		.w{{fill:white}}
		]]></style>
	</defs>
	<rect width="{0}" height="{0}" x="0" y="0" style="fill:white;stroke:white"/>\n'''.format(2*self.padding+18*self.gridSize)
		self.footer="</svg>\n"

		grid='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" />\n'

		# okraje desky
		for i in (0,18):
			self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding)
			self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\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(padding, 18*c+padding, c*i+padding, c*i+padding)
			self.content+=grid.format(c*i+padding, c*i+padding, padding, 18*c+padding)

		# hvězdy
		for i in range(3):
			for j in range(3):
				self.content+='  <circle cx="{0}" cy="{1}" r="{2}" class="b"/>\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+='  <circle cx="{0}" cy="{1}" r="{2}" class="{3}" />\n'.format(padding+x*c, padding+y*c, c/2-1, color)

	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+='  <text x="{0}" y="{1}" class="{2}" font-size="{3}">{4}</text>\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


class Tikz:
	content=""
	footer=""
	extension="tex"
	
	highNumbers=True
	
	def __init__(self):
		self.content=r'''\begin{tikzpicture}
	\draw[step=\boardSquare,gray,very thin] (0,0) grid (18\boardSquare,18\boardSquare);
	\draw (0,0) rectangle (18\boardSquare,18\boardSquare);
	
	'''
		
		# hvězdy
		for i in range(3):
			for j in range(3):
				self.content+=r'''  \filldraw[fill=black] ({0}\boardSquare,{1}\boardSquare) circle[radius=0.04];'''.format(6*i+3, 6*j+3)+'\n'
			self.content+='\n'
	
		self.footer=r'\end{tikzpicture}' '\n'
			
	def __str__(self):
		return self.content+self.footer

	def drawStone(self,x,y,color):
		fill="black" if color=="b" else "white"
		self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare];'.format(fill,x,18-y)+'\n'
	
	def drawMove(self,x,y,label,color):
		fill="black" if color=="b" else "white"
		labelColor="white" if color=="b" else "black"
		if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
		
		self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill,x,18-y,labelColor,label)+'\n'
		
	def getContent(self):
		return self.content+self.footer


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()

	localBoard=dict()
	overlays=""
	letters=dict()
	letter='a'

	diagramsNeeded=(len(moves)-minMovesPerDiagram)//movesPerDiagram+1
	moveNumber=0
	
	for i in range(diagramsNeeded):
		# inicializuj diagram
		diagram=Tikz()
		
		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}
		
		for j in range(movesPerDiagram):
			# kresli tahy
			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):
				print("illegal move: {0} at {1},{2}".format(moveNumber+1,x,y))
				moveNumber+=1
				continue
			
			# zapíšu tah na volný průsečík
			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
			elif localBoard[(x,y)]<1:
				# průsečík není popsaný ani písmenem
				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)
					letter=chr(ord(letter)+1)
				overlays+="{0} = {1}\n".format(moveNumber+1,letters[(x,y)])
			# průsečík je obsazený očíslovaným kamenem
			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())
		t.close()
			
	notes=open(os.path.join(os.path.dirname(__file__),"out","{0}.txt".format(shortName)),'w')
	notes.write(overlays)
	notes.close()
	
print("processing:")
for item in files:
	# relativně vůči work directory nebo vůči skriptu?
	# item=os.path.join(os.path.dirname(__file__),item)
	if os.path.isfile(item):
		print("{0}... ".format(item),end="")
		processFile(item)
		print("done")
	elif os.path.isdir(item):
		files+=[os.path.join(item,child) for child in os.listdir(item)]
		print("contents of the '{0}' directory added to the queue".format(item))
	else: print("the '{0}' path could not be resolved to either a file nor a directory".format(item))