Files @ d57d0d4ede15
Branch filter:

Location: Diana/src/diana/sgfParser/node.py - annotation

Laman
changed the naming convention to follow standards
616c96178973
36b0271e7393
616c96178973
d57d0d4ede15
616c96178973
616c96178973
616c96178973
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
616c96178973
686166c7d5bc
616c96178973
686166c7d5bc
d57d0d4ede15
686166c7d5bc
616c96178973
d57d0d4ede15
d57d0d4ede15
686166c7d5bc
d57d0d4ede15
616c96178973
686166c7d5bc
616c96178973
686166c7d5bc
d57d0d4ede15
686166c7d5bc
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
686166c7d5bc
d57d0d4ede15
686166c7d5bc
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
616c96178973
616c96178973
d57d0d4ede15
616c96178973
616c96178973
616c96178973
686166c7d5bc
616c96178973
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
616c96178973
686166c7d5bc
616c96178973
616c96178973
616c96178973
616c96178973
616c96178973
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
616c96178973
d57d0d4ede15
686166c7d5bc
686166c7d5bc
686166c7d5bc
686166c7d5bc
616c96178973
616c96178973
616c96178973
616c96178973
616c96178973
616c96178973
e3e6dfbb44f6
686166c7d5bc
686166c7d5bc
616c96178973
686166c7d5bc
686166c7d5bc
686166c7d5bc
686166c7d5bc
e3e6dfbb44f6
616c96178973
d57d0d4ede15
d57d0d4ede15
e3e6dfbb44f6
d57d0d4ede15
686166c7d5bc
686166c7d5bc
616c96178973
d57d0d4ede15
686166c7d5bc
616c96178973
616c96178973
from collections import deque
import logging as log

from . import skip_whitespace, ParserWarning
from .property import Property, GAME_INFO


class Node:
	def __init__(self):
		self.properties = dict()
		self.parent = None
		self.children = []

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

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

		i = skip_whitespace(s, start + 1)
		while Property.fits(s, i):
			(i, x) = Property.create(s, i)
			if x.name in res.properties:
				log.warning(ParserWarning('duplicate "{0}" property in a node. second value ignored'.format(x.name), s, i))
			else:
				res.properties[x.name] = x
			i = skip_whitespace(s, i)
		return (i, res)

	def list_gi_nodes(self):
		if self.is_gi_node():
			yield self
		empty = not self.is_gi_node()

		node = self
		while node.parent:
			node = node.parent
			if node.is_gi_node():
				empty = False
				yield node

		queue = deque(self.children)
		while len(queue) > 0:
			node = queue.popleft()
			if node.is_gi_node():
				empty = False
				yield node
			queue.extend(node.children)
		if empty:
			yield self  # always yield at least self, can work as GINode as well as any other

	def is_gi_node(self):
		return any(prop.type == GAME_INFO for prop in self.properties.values())

	def set_prop(self, name, value):
		self.properties[name] = value
		# check value type

	def set_children(self, children):
		self.children = children
		for child in children:
			child.parent = self

	def add_child(self, node):
		if node in self.children:
			return node
		node.parent = self
		self.children.append(node)
		return node

	def remove_child(self, node):
		if node not in self.children:
			return None
		del self.children[self.children.index(node)]
		node.parent = None
		return node

	def remove_child_at(self, i):
		if -len(self.children) < i < len(self.children):
			res = self.children[i]
			del self.children[i]
			res.parent = None
			return res
		return None

	## Create a copy of the Node, with the same parent and deep copied properties, no copied children.
	def copy(self):
		res = Node()
		res.properties = {k: v.copy() for (k, v) in self.properties.items()}
		res.parent = self.parent
		return res

	def get_prop(self, name, default=None):
		if name in self.properties:
			return self.properties[name].value
		else:
			return default

	## Returns textual representation of the Node itself, but disregards its children.
	def __str__(self):
		return ";" + "".join(str(p) for p in self.properties.values())

	def export(self):
		# there is a beautiful recursive solution, which this stack is too narrow to contain
		stack = [(self, 1, 1)]
		output = []

		while len(stack) > 0:
			(node, left, right) = stack.pop()
			if left > 0:
				output.append("("*left)
			output.append(str(node)+"\n")

			child_count = len(node.children)
			if child_count == 0:  # a leaf
				output.append(")"*right+"\n")
			elif child_count == 1:  # a line
				stack.append((node.children[0], 0, right))
			else:  # a branching node
				# first child pops first, last child closes parent's parentheses
				children = zip(node.children, [1]*child_count, [1]*(child_count-1)+[1+right])
				stack.extend(reversed(list(children)))

		return "".join(output)