Changeset - c705c709565b
[Not reviewed]
default
0 4 1
Laman - 8 years ago 2017-02-05 22:02:28

enhanced SVG, added pleb.svg circumventing a rendering bug in librsvg
5 files changed with 42 insertions and 18 deletions:
0 comments (0 inline, 0 general)
.hgignore
Show inline comments
 
^\.
 
__pycache__/
 
^in/
 
^out/
 
\.pyc$
src/diana.py
Show inline comments
 
import os
 
import re
 
import sys
 

	
 
from jinja2 import Environment,FileSystemLoader
 

	
 
import go
 
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()
 
env=Environment(loader=FileSystemLoader(templateDir))
 

	
 

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

	
 
movesPerDiagram=75
 
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
 

	
 
	games=Collection(open(fileName, 'r', encoding="utf-8").read()).listGames()
 
	record=list(games)[0]
 

	
 
	moves=list(collectMoves(record))
 

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

	
 
	diagramsNeeded=(len(moves)-minMovesPerDiagram)//movesPerDiagram+1
 
	moveNumber=0
 
	
 
	for i in range(diagramsNeeded):
 
		# initialize the diagram
 
		diagram=Svg()
 
		
 
		for lineNumber,line in enumerate(game.board):
 
			for itemNumber,item in enumerate(line):
 
				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):
 
			# draw the moves
 
			if moveNumber>=len(moves): break
 

	
 
			c,(x,y)=moves[moveNumber]
 
			c=c.lower()
 
			
 
			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
 

	
 
			# draw the move on an empty intersection
 
			if not (x,y) in localBoard:
 
				localBoard[(x,y)]=moveNumber+1
 
				diagram.addMove(x,y,c,moveNumber+1)
 
			# intersection occupied by an unlabeled stone
 
			elif localBoard[(x,y)]<1:
 
				# intersection not labeled even by a letter
 
				if not (x,y) in letters:
 
					letters[(x,y)]=letter
 
					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)])
 
			# intersection occupied by a numbered stone
 
			else: overlays+="{0} = {1}\n".format(moveNumber+1,localBoard[(x,y)])
 
			
 
			moveNumber+=1
 
			
 
		# 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.write(diagram.render(env.get_template("templ.svg")))
 
		t.close()
 
			
 
	notes=open(os.path.join("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))
src/drawer/svg.py
Show inline comments
 
@@ -3,62 +3,61 @@ 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:
 
	extension="svg"
 

	
 
	padding=15
 
	highNumbers=True
 
	
 
	def __init__(self):
 
		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))
 

	
 
	def addMove(self,x,y,color,label):
 
		if (not self.highNumbers) and isinstance(label,int) and label%100!=0:
 
			label%=100
 

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

	
 
	def render(self, template):
 
		points = [p for (i,p) in sorted(self._index.values())]
 

	
 
		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}
 

	
 
		return svg.render(params)
 
		return template.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+='  <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)
src/templ/templ-pleb.svg
Show inline comments
 
new file 100644
 
{% extends "templ.svg" %}
 

	
 
{% block style %}
 
rect{fill:white;stroke:black;stroke-width:1px}
 
text{font-family:"DejaVu Sans";text-anchor:middle;}
 
line{stroke:black;stroke-width:0.7px}
 
circle{stroke:black}
 
circle.b, text.w, text.e{fill:black}
 
circle.w, text.b{fill:white}
 
circle.e {stroke:none;fill:white}
 
{% endblock %}
 

	
 
{% macro labeledPoint(p) %}
 
<g transform="translate({{(p.x*cellSize) | round(2)}},{{(p.y*cellSize) | round(2)}})">
 
	<circle class="{{p.color or 'e'}}" cx="0" cy="0" r="{{stoneRadius|round(2)}}"/>
 
	<text class="{{p.color or 'e'}}" y="0.4em">{{p.label}}</text>
 
</g>
 
{% endmacro %}
src/templ/templ.svg
Show inline comments
 
<?xml version="1.0" standalone="no"?>
 
<?xml version="1.0" encoding="utf-8"?>
 
{% set cellSize=boardSize/18 %}
 
{% set stoneRadius=cellSize/2-1 %}
 

	
 
<svg width="{{boardSize+padding*2}}" height="{{boardSize+padding*2}}" version="1.1" xmlns="http://www.w3.org/2000/svg" alignment-baseline="center">
 
{% if not labeledPoint %}
 
	{% macro labeledPoint(p) %}
 
	<g class="{{p.color or 'e'}}" transform="translate({{(p.x*cellSize) | round(2)}},{{(p.y*cellSize) | round(2)}})">
 
		<circle cx="0" cy="0" r="{{stoneRadius|round(2)}}"/>
 
		<text y="0.4em">{{p.label}}</text>
 
	</g>
 
	{% endmacro %}
 
{% endif %}
 

	
 
<svg width="{{boardSize+padding*2}}" height="{{boardSize+padding*2}}" version="1.1" xmlns="http://www.w3.org/2000/svg">
 
	<defs>
 
		<style type="text/css"><![CDATA[
 
			rect{fill:white;stroke:black;stroke-width:1}
 
		{% block style %}
 
			rect{fill:white;stroke:black;stroke-width:1px}
 
			text{font-family:"DejaVu Sans";text-anchor:middle;}
 
			line{stroke:black;stroke-width:0.7}
 
			line{stroke:black;stroke-width:0.7px}
 
			circle{stroke:black}
 
			circle.b, .b circle, .w text, .e text{fill:black}
 
			circle.w, .w circle, .b text{fill:white}
 
			.e circle {stroke:none;fill:white}
 
		{% endblock %}
 
		]]></style>
 
	</defs>
 
	<g width="{{boardSize}}" height="{{boardSize}}" transform="translate({{padding}},{{padding}})">
 
	<g transform="translate({{padding}},{{padding}})">
 
		<rect x="0" y="0" width="{{boardSize}}" height="{{boardSize}}"/>
 
		{# grid #}
 
		{% for i in range(1,18) %}
 
			<line x1="0" x2="{{boardSize}}" y1="{{(i*cellSize) | round(2)}}" y2="{{(i*cellSize) | round(2)}}"/>
 
			<line x1="{{(i*cellSize) | round(2)}}" x2="{{(i*cellSize) | round(2)}}" y1="0" y2="{{boardSize}}"/>
 
		{% endfor %}
 

	
 
		{# stars #}
 
		{% for y in [3,9,15] %}
 
			{% for x in [3,9,15] %}
 
		  <circle cx="{{(x*cellSize) | round(2)}}" cy="{{(y*cellSize) | round(2)}}" r="2" class="b"/>
 
			{% endfor %}
 
		{% endfor %}
 

	
 
		{# stones #}
 
		{% for p in stones %}
 
			<circle cx="{{(p.x*cellSize) | round(2)}}" cy="{{(p.y*cellSize) | round(2)}}" r="{{stoneRadius|round(2)}}" class="{{p.color}}"/>
 
		{% endfor %}
 

	
 
		{# moves #}
 
		{% for p in moves %}
 
			<g width="{{cellSize|round(2)}}" height="{{cellSize|round(2)}}" class="{{p.color}}" transform="translate({{(p.x*cellSize) | round(2)}},{{(p.y*cellSize) | round(2)}})">
 
				<circle cx="0" cy="0" r="{{stoneRadius|round(2)}}"/>
 
				<text y="0.4em">{{p.label}}</text>
 
			</g>
 
			{{labeledPoint(p)}}
 
		{% endfor %}
 

	
 
		{# labels #}
 
		{% for p in labels %}
 
			<g width="{{cellSize|round(2)}}" height="{{cellSize|round(2)}}" class="e" transform="translate({{(p.x*cellSize) | round(2)}},{{(p.y*cellSize) | round(2)}})">
 
				<circle cx="0" cy="0" r="{{stoneRadius|round(2)}}"/>
 
				<text y="0.4em">{{p.label}}</text>
 
			</g>
 
			{{labeledPoint(p)}}
 
		{% endfor %}
 
	</g>
 
</svg>
0 comments (0 inline, 0 general)