Files @ 31266616bb87
Branch filter:

Location: Diana/src/diana.py

Laman
split diagram notes into separate text files, refactored diana.py
import os
import re

from jinja2 import Environment,FileSystemLoader

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


curDir=os.path.dirname(__file__)
templateDir=os.path.join(curDir,"templ")
env=Environment(loader=FileSystemLoader(templateDir))


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]


class SourceFile:
	def __init__(self,fileName):
		self.fileName=fileName
		self._shortName= "".join(re.split(r'[/\\]', fileName)[-1].split('.')[:-1])
		self._game=go.Go()
		self._moveNumber=0
		self._moves=[]

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

		try:
			games=Collection(open(self.fileName, 'r', encoding=cfg.encoding).read()).listGames()
		except ParserError as e:
			print("Couldn't parse {0}, following error occured: {1}".format(self.fileName,e))
			return False
		record=list(games)[0]

		self._moves=list(collectMoves(record))

		diagramsNeeded=(len(self._moves)-cfg.minMovesPerDiagram)//cfg.movesPerDiagram+1

		for i in range(diagramsNeeded):
			self.createDiagram(i+1)

		notes=open(os.path.join(cfg.outputDir,"{0}.txt".format(self._shortName)), 'w')
		# notes.write(overlays)
		notes.close()
		print("done")

	def createDiagram(self,diagramNumber):
		# initialize the diagram
		template=Svg()
		overlays=[]
		letters=dict()
		letter="a"

		for lineNumber,line in enumerate(self._game.board):
			for itemNumber,item in enumerate(line):
				if item==BLACK: template.addStone(itemNumber,lineNumber,"b")
				if item==WHITE: template.addStone(itemNumber,lineNumber,"w")
			localBoard={(a,b):self._game.board[b][a]-1 for a in range(19) for b in range(19) if self._game.board[b][a]!=EMPTY}

		for j in range(cfg.movesPerDiagram):
			# draw the moves
			if self._moveNumber>=len(self._moves): break

			c,move=self._moves[self._moveNumber]
			c=c.lower()
			if move==tuple():
				overlays.append("{0} pass".format(self._moveNumber))
				self._moveNumber+=1
				continue
			else:
				(x,y)=move

			if not self._game.move(BLACK if c=='b' else WHITE, x,y):
				# !! we do not honor http://red-bean.com/sgf/ff5/m_vs_ax.htm at the moment
				msg="illegal move: {0} at {1},{2}".format(self._moveNumber+1,x,y)
				if cfg.keepBroken:
					print(msg)
					self._moveNumber+=1
					continue
				else:
					msg+=". aborted"
					print(msg)
					return False

			# draw the move on an empty intersection
			if not (x,y) in localBoard:
				localBoard[(x,y)]=self._moveNumber+1
				template.addMove(x,y,c,self._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'
					template.addMove(x,y,color,letter)
					letter=chr(ord(letter)+1)
				overlays.append("{0} = {1}".format(self._moveNumber+1,letters[(x,y)]))
			# intersection occupied by a numbered stone
			else: overlays.append("{0} = {1}".format(self._moveNumber+1,localBoard[(x,y)]))

			self._moveNumber+=1
		
		# finish and save the diagram
		file=open(os.path.join(cfg.outputDir,"{0}-{1}.{2}".format(self._shortName,diagramNumber,template.extension)),'w') # a new file
		file.write(template.render(env.get_template("templ.svg")))
		file.close()

		notes=open(os.path.join(cfg.outputDir,"{0}-{1}.txt".format(self._shortName,diagramNumber)), 'w')
		notes.write("\n".join(overlays))
		notes.close()


print("processing:")
files=cfg.inputFiles[:]

for item in files:
	if os.path.isfile(item):
		f=SourceFile(item)
		f.process()
	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))