Changeset - 3207d998d598
[Not reviewed]
tip default
0 4 1
Laman - 3 years ago 2022-03-06 17:08:22

reintroduced tikz output format
5 files changed with 76 insertions and 38 deletions:
0 comments (0 inline, 0 general)
src/diana/config.py
Show inline comments
 
@@ -4,25 +4,25 @@ from argparse import ArgumentParser
 

	
 
PROG_NAME = "DianaXO"
 
VERSION = (0, 1, 0)
 

	
 
cur_dir = os.path.dirname(__file__)
 

	
 
parser = ArgumentParser()
 
parser.add_argument("--encoding")
 
parser.add_argument("-s", "--suffix")
 
parser.add_argument("-r", "--recursive")
 
parser.add_argument("-i", "--input", nargs="+", required=True)
 
parser.add_argument("-o", "--output")
 
parser.add_argument("--format", choices={"svg"})
 
parser.add_argument("--format", choices={"svg", "tikz"})
 
parser.add_argument("-k", "--keep-broken")
 
parser.add_argument("--moves-p-d", type=int)
 
parser.add_argument("--min-p-d", type=int)
 
parser.add_argument("--version", action="version", version="{0} {1}.{2}.{3}".format(PROG_NAME, *VERSION))
 

	
 

	
 
input_files = []
 
encoding = "utf-8-sig"
 
sgf_suffix = True
 
recursive = False
 
output_dir = cur_dir
 
output_format = "svg"
src/diana/diana.py
Show inline comments
 
@@ -21,63 +21,64 @@ def collect_moves(root):
 
		b = node.get_prop("B")
 
		w = node.get_prop("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]
 

	
 

	
 
class SourceFile:
 
	def __init__(self, file_name):
 
	def __init__(self, file_name, output_format):
 
		self.file_name = file_name
 
		self._short_name = "".join(re.split(r'[/\\]', file_name)[-1].split('.')[:-1])
 
		self._game = go.Go()
 
		self.drawer = Tikz if output_format == "tikz" else Svg
 

	
 
		with open(self.file_name, 'r', encoding=cfg.encoding) as f:
 
			games = Collection(f.read()).list_games()
 
		self._record = list(games)[0]
 
		self._moves = list(collect_moves(self._record.root))
 

	
 
	def process(self):
 
		print("{0}... ".format(self.file_name), end="")
 

	
 
		i = 1
 
		for k in range(0, len(self._moves), cfg.moves_per_diagram):
 
			filename = os.path.join(cfg.output_dir, "{0}-{1}".format(self._short_name, i))
 
			self.create_diagram(k, k + cfg.moves_per_diagram).save(filename, "templ-pleb.svg")
 
			self.create_diagram(k, k+cfg.moves_per_diagram).save(filename)
 
			i += 1
 

	
 
		info_str = """{GN}
 
B: {PB} {BR}
 
W: {PW} {WR}
 
{DT}
 
{RE}""".format(**self.fetch_game_info(["GN", "PB", "BR", "PW", "WR", "DT", "RE"], ""))
 
		notes = open(os.path.join(cfg.output_dir, "{0}.txt".format(self._short_name)), 'w')
 
		notes.write(info_str)
 
		notes.close()
 
		print("done")
 

	
 
	def create_diagram(self, start, end):
 
		"""Create and return a diagram drawer instance.
 

	
 
		:param int start: the initial move
 
		:param int end: the first omitted move, similar to sequence slices
 
		:return: a diagram instance
 
		:rtype: Drawer"""
 

	
 
		# initialize the diagram
 
		template = Svg()
 
		template = self.drawer(start)
 

	
 
		self._set_move(start)
 

	
 
		# draw current state
 
		for (line_number, line) in enumerate(self._game.board):
 
			for (item_number, item) in enumerate(line):
 
				if item != EMPTY:
 
					template.add_stone(item_number, line_number, "b" if item == BLACK else "w")
 

	
 
		# draw the moves
 
		for k in range(start, end):
 
			if k >= len(self._moves):
 
@@ -88,25 +89,25 @@ W: {PW} {WR}
 
				template.overlays.append((k, "pass"))
 
				continue
 
			else:
 
				(c, r) = move
 

	
 
			if not self._move(color, c, r):
 
				if cfg.keep_broken:
 
					continue
 
				else:
 
					return False
 

	
 
			# draw the move
 
			template.add_move(c, r, color, k + 1)
 
			template.add_move(c, r, color, k+1)
 

	
 
		return template
 

	
 
	def fetch_game_info(self, field_names, default=None):
 
		return {k: self._record.get(k, default) for k in field_names}
 

	
 
	def _set_move(self, k):
 
		"""Rewind the internal game state to move k.
 

	
 
		:param int k: the move number"""
 
		self._game = go.Go()
 

	
 
@@ -144,21 +145,21 @@ W: {PW} {WR}
 
				return False
 
		return True
 

	
 

	
 
def main():
 
	cfg.parse_args()
 
	print("processing:")
 
	files = cfg.input_files[:]
 

	
 
	for item in files:
 
		if os.path.isfile(item):
 
			try:
 
				f = SourceFile(item)
 
				f = SourceFile(item, cfg.output_format)
 
				f.process()
 
			except ParserError as e:
 
				print("Couldn't parse {0}, following error occured: {1}".format(item, e))
 
		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/diana/drawer/svg.py
Show inline comments
 
@@ -28,25 +28,26 @@ class Svg(Drawer):
 
		:param str template_name: a template file name in the templ directory
 
		:param bgcolor: a background color
 
		:type bgcolor: an SVG color, which is the same as a CSS color
 
		:return: the rendered template string"""
 
		points = [p for (i, p) in sorted(self._index.values(), key=lambda x: x[0])]
 

	
 
		stones = [p for p in points if p.color and 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]
 

	
 
		params = {
 
			"boardSize": self.boardSize, "padding": self.padding, "stones": stones, "moves": moves,
 
			"labels": labels, "adjustFont": adjust_font, "bgcolor": bgcolor}
 
			"labels": labels, "adjustFont": adjust_font, "bgcolor": bgcolor
 
		}
 

	
 
		return self._env.get_template(template_name).render(params)
 

	
 
	def save(self, filename, template="templ.svg", bgcolor=""):
 
		"""Render the template and save it with the filename.
 

	
 
		:param str filename: a path where to save the diagram. SVG and TXT suffixes will be appended
 
		:param str template: a template file name in the templ directory
 
		:param bgcolor: a background color
 
		:type bgcolor: an SVG color, which is the same as a CSS color"""
 
		file = open(filename+".svg", 'w')
 
		file.write(self.render(template, bgcolor))
src/diana/drawer/tikz.py
Show inline comments
 
class Tikz:
 
	content = ""
 
	footer = ""
 
	extension = "tex"
 
from .base import Drawer
 

	
 

	
 
def stone_color(c):
 
	if c == "b":
 
		return "black"
 
	elif c == "w":
 
		return "white"
 
	else:
 
		return c
 

	
 

	
 
def label_color(c):
 
	return stone_color("b" if c == "w" else "w" if c == "b" else c)
 

	
 

	
 
class Tikz(Drawer):
 
	high_numbers = 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);
 

	
 
	'''
 
	def render(self, template_name, bgcolor=""):
 
		points = [p for (i, p) in sorted(self._index.values(), key=lambda x: x[0])]
 

	
 
		# stars
 
		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'
 
		stones = [p for p in points if p.color and 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]
 

	
 
	def __str__(self):
 
		return self.content+self.footer
 
		params = {
 
			"stones": stones, "moves": moves, "labels": labels, "bgcolor": bgcolor,
 
			"stone_color": stone_color, "label_color": label_color
 
		}
 

	
 
	def draw_stone(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'
 
		return self._env.get_template(template_name).render(params)
 

	
 
	def draw_move(self, x, y, label, color):
 
		fill = "black" if color == "b" else "white"
 
		label_color = "white" if color == "b" else "black"
 
		if (not self.high_numbers) and isinstance(label, int) and label%100 != 0:
 
			label = label%100
 
	def save(self, filename, template="templ.tex", bgcolor=""):
 
		file = open(filename + ".tikz", 'w')
 
		file.write(self.render(template, bgcolor))
 
		file.close()
 

	
 
		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, label_color, label)+'\n'
 

	
 
	def get_content(self):
 
		return self.content+self.footer
 
		super().save(filename)
src/diana/templ/templ.tikz
Show inline comments
 
new file 100644
 
\documentclass{article}
 
\usepackage{tikz}
 
\newlength{\boardSquare}
 
\setlength{\boardSquare}{6mm}
 

	
 
\begin{document}
 
\begin{tikzpicture}
 

	
 
% grid
 
\draw[step=\boardSquare,gray,very thin] (0,0) grid (18\boardSquare,18\boardSquare);
 
\draw (0,0) rectangle (18\boardSquare,18\boardSquare);
 

	
 
% stars
 
{% for y in [3,9,15] %}
 
	{% for x in [3,9,15] %}
 
		\filldraw[fill=black] ({{x}}\boardSquare,{{y}}\boardSquare) circle[radius=0.04];
 
	{% endfor %}
 
{% endfor %}
 

	
 
% stones
 
{% for p in stones %}
 
	\filldraw[draw=black,fill={{stone_color(p.color)}}] ({{p.x}}\boardSquare,{{p.y}}\boardSquare) circle[radius=0.5\boardSquare];
 
{% endfor %}
 

	
 
% moves
 
{% for p in moves -%}
 
	\filldraw[draw=black,fill={{stone_color(p.color)}}] ({{p.x}}\boardSquare,{{p.y}}\boardSquare) circle[radius=0.5\boardSquare] node[color={{label_color(p.color)}}]{{ '{'+p.label|string+'}' }};
 
{% endfor %}
 

	
 
% labels
 
{% for p in labels -%}
 
	{{labeledPoint(p)}}
 
{% endfor %}
 

	
 
\end{tikzpicture}
 
\end{document}
0 comments (0 inline, 0 general)