Changeset - afabea7d0e61
[Not reviewed]
default
7 3 7
Laman - 3 years ago 2022-03-05 22:19:35

renamed sgfparser, game_record, prop_values
10 files changed with 11 insertions and 11 deletions:
0 comments (0 inline, 0 general)
src/diana/diana.py
Show inline comments
 
import os
 
import re
 

	
 
from . import config as cfg
 
from . import go
 
from .go import BLACK, WHITE, EMPTY
 
from .sgfParser import ParserError
 
from .sgfParser.collection import Collection
 
from .sgfparser import ParserError
 
from .sgfparser.collection import Collection
 
from .drawer.svg import Svg
 
from .drawer.tikz import Tikz
 

	
 

	
 
def collect_moves(root):
 
	node = root
 
	while len(node.children) > 0:
 
		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):
 
		self.file_name = file_name
 
		self._short_name = "".join(re.split(r'[/\\]', file_name)[-1].split('.')[:-1])
 
		self._game = go.Go()
 

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

	
src/diana/drawer/base.py
Show inline comments
 
import os
 
from itertools import count
 

	
 
from jinja2 import Environment, FileSystemLoader
 

	
 

	
 
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 Base:
 
class Drawer:
 
	high_numbers = True
 

	
 
	def __init__(self, start=0):
 
		self.overlays = []
 
		self._letter = "a"
 

	
 
		self._index = dict()
 
		self._index_gen = count(start)
 

	
 
		cur_dir = os.path.dirname(__file__)
 
		template_dir = os.path.join(cur_dir, "..", "templ")
 
		self._env = Environment(loader=FileSystemLoader(template_dir))
 
		self._env.trim_blocks = True
 
		self._env.lstrip_blocks = True
 

	
 
	def add_stone(self, x, y, color):
 
		assert (x, y) not in self._index
 
		self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, color))
 

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

	
 
		if (x, y) not in self._index:
 
			self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, color, label))
 
		else:
 
			(_, point) = self._index[(x, y)]
 
			if not point.label:
 
				point.label = self._letter
 
				self._letter = chr(ord(self._letter)+1)
 
			self.overlays.append((label, point.label))
 

	
 
	def add_label(self, x, y, label):
 
		self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, "", label))
 

	
 
	def save(self, filename):
 
		notes = open(filename+".txt", 'w')
 
		notes.write("\n".join("{0} = {1}".format(a, b) for (a, b) in self.overlays))
 
		notes.close()
src/diana/drawer/svg.py
Show inline comments
 
from .base import Base
 
from .base import Drawer
 

	
 

	
 
def adjust_font(base, text):
 
	text = str(text)
 
	if len(text) < 2:
 
		return round(0.7*base)
 
	elif len(text) < 3:
 
		return round(0.55*base)
 
	else:
 
		return round(0.4*base)
 

	
 

	
 
class Svg(Base):
 
class Svg(Drawer):
 
	extension = "svg"
 

	
 
	padding = 15
 
	high_numbers = True
 
	
 
	def __init__(self, start=0):
 
		super().__init__(start)
 
		self.boardSize = 480
 
		self.padding = 30
 

	
 
	def render(self, template_name, bgcolor=""):
 
		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}
 

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

	
 
	def save(self, filename, template="templ.svg", bgcolor=""):
 
		file = open(filename+".svg", 'w')
 
		file.write(self.render(template, bgcolor))
 
		file.close()
 

	
 
		super().save(filename)
src/diana/sgfparser/__init__.py
Show inline comments
 
file renamed from src/diana/sgfParser/__init__.py to src/diana/sgfparser/__init__.py
src/diana/sgfparser/collection.py
Show inline comments
 
file renamed from src/diana/sgfParser/collection.py to src/diana/sgfparser/collection.py
 
from .node import Node
 
from . import skip_whitespace, ParserError
 
from .gameRecord import GameRecord
 
from .game_record import GameRecord
 

	
 

	
 
class Collection:
 
	def __init__(self, s):
 
		self.game_trees = []
 
		i = skip_whitespace(s, 0)
 
		if i >= len(s):
 
			return
 
		elif not GameTree.fits(s, i):
 
			raise ParserError("expected a GameTree starting with '('", s, i)
 
		while GameTree.fits(s, i):
 
			(i, x) = GameTree.create(s, i)
 
			self.game_trees.append(x)
 
		if i < len(s):
 
			raise ParserError("expected EOF", s, i)
 

	
 
	def list_games(self):
 
		for tree in self.game_trees:
 
			for game in tree.list_games():
 
				yield game
 

	
 

	
 
class GameTree:
 
	def __init__(self):
 
		self.nodes = []
 
		self.branches = []
 

	
 
	@staticmethod
 
	def fits(s, i):
 
		return i < len(s) and s[i] == "("
 

	
 
	@staticmethod
 
	def create(s, start):
 
		assert GameTree.fits(s, start)
 
		res = GameTree()
 

	
 
		i = skip_whitespace(s, start + 1)
 
		if not Node.fits(s, i):
 
			raise ParserError("expected a Node starting with ';'", s, i)
 

	
 
		y = None
 
		while Node.fits(s, i):
 
			(i, x) = Node.create(s, i)
 
			res.nodes.append(x)
 
			if y:
 
				y.add_child(x)
 
			x.parent = y
 
			y = x
src/diana/sgfparser/game_record.py
Show inline comments
 
file renamed from src/diana/sgfParser/gameRecord.py to src/diana/sgfparser/game_record.py
src/diana/sgfparser/node.py
Show inline comments
 
file renamed from src/diana/sgfParser/node.py to src/diana/sgfparser/node.py
src/diana/sgfparser/prop_values.py
Show inline comments
 
file renamed from src/diana/sgfParser/propValues.py to src/diana/sgfparser/prop_values.py
src/diana/sgfparser/property.py
Show inline comments
 
file renamed from src/diana/sgfParser/property.py to src/diana/sgfparser/property.py
 
import re
 
from datetime import date
 
import logging as log
 

	
 
from .propValues import choose, singleton, list_of, compose, number, real, double, color, text, empty, anything, point, move, stone
 
from .prop_values import choose, singleton, list_of, compose, number, real, double, color, text, empty, anything, point, move, stone
 
from . import skip_whitespace, ParserError
 

	
 
GAME_INFO = 1
 
UNKNOWN = 99
 

	
 

	
 
class DateException(Exception):
 
	pass
 

	
 

	
 
class Property:
 
	ident_regexp = re.compile(r"[A-Z]+")
 

	
 
	def __init__(self):
 
		self.name = ""
 
		self.value = ""
 

	
 
	@staticmethod
 
	def fits(s, i):
 
		return i < len(s) and s[i].isupper()
 

	
 
	@staticmethod
 
	def create(s, start):
 
		assert Property.fits(s, start)
 
		res = Property()
 
		(i, res.name) = Property.ident(s, start)
 
		i = skip_whitespace(s, i)
 
		try:
 
			(i, x) = Property.create_value(s, i, res.name)
 
		except ParserError as e:  # a malformed value
 
			log.warning(e)
 
			(i, x) = choose(list_of(anything), singleton(anything))(s, i)
 
			res.name = "_"+res.name
 
		res.value = x
 
		if res.name == "DT":
 
			res = DateProperty(x)
 
		i = skip_whitespace(s, i)
 
		return (i, res)
 

	
 
	@staticmethod
 
	def ident(s, start):
 
		m = Property.ident_regexp.match(s, start)
 
		if m is None:
 
			raise ParserError("expected a property identifier matching '[A-Z]+'", s, start)
 
		return (m.end(), m.group())
 

	
 
	@staticmethod
 
	def create_value(s, start, name):
src/diana/tests/test_sgf_parser.py
Show inline comments
 
file renamed from src/diana/tests/testSgfParser.py to src/diana/tests/test_sgf_parser.py
 
from itertools import chain
 
from datetime import date
 
import unittest
 
from unittest import TestCase
 
import os
 

	
 
from ..sgfParser import str_row_col
 
from ..sgfParser.collection import Collection
 
from ..sgfParser.property import Property, DateProperty, DateException
 
from ..sgfParser.propValues import text, compose
 
from ..sgfparser import str_row_col
 
from ..sgfparser.collection import Collection
 
from ..sgfparser.property import Property, DateProperty, DateException
 
from ..sgfparser.prop_values import text, compose
 

	
 

	
 
dataDir = os.path.join(os.path.dirname(__file__), "data")
 

	
 

	
 
class TestUtils(TestCase):
 
	def testTextPos(self):
 
		s = "abc\ndef\rgh\r\nij\n\rklmn"
 
		rc = [
 
			[1, 2, 3, 4],
 
			[1, 2, 3, 4],
 
			[1, 2, 3, 4],
 
			[1, 2, 3], [1],  # don't care about LFCR, we unicode now
 
			[1, 2, 3, 4]
 
		]
 
		res = chain((r+1, c) for (r, row) in enumerate(rc) for c in row)
 
		for (i, (r, c)) in zip(range(len(s)+1), res):
 
			self.assertEqual(str_row_col(s, i), (r, c))
 

	
 

	
 
class TestProperty(TestCase):
 
	def testName(self):
 
		with self.assertRaises(AssertionError):
 
			Property.create("[99]", 0)
 
		with self.assertRaises(AssertionError):
 
			Property.create("99[99]", 0)
 

	
 
		(i, prop) = Property.create("MN[99]", 0)
 
		self.assertNotEqual((i, prop), (0, None))
 
		self.assertEqual((i, prop.name), (6, "MN"))
 

	
 
	def testText(self):
 
		s = r"""[abc\
 
def
 
ghi]"""
 
		self.assertEqual(text()(s, 1)[1], "abcdef ghi")
 
		self.assertEqual(text(False)(s, 1)[1], "abcdef\nghi")
 

	
 
		s = """[m\\no\\\tpqr\\]\\\\]"""
 
		self.assertEqual(text()(s, 1)[1], "mno pqr]\\")
 
		self.assertEqual(text(False)(s, 1)[1], "mno pqr]\\")
 

	
 
		s = """[abc:def]"""
 
		parsed = compose(text(composed=True), text(composed=True))(s, 1)
 
		self.assertEqual(str(parsed[1]), "abc:def")
 

	
 

	
 
class TestDateProperty(TestCase):
0 comments (0 inline, 0 general)