Changeset - afb861f616bf
[Not reviewed]
default
0 3 0
Laman - 6 years ago 2019-05-29 16:37:59

better configuration handling
3 files changed with 40 insertions and 21 deletions:
0 comments (0 inline, 0 general)
.hgignore
Show inline comments
 
^\.
 
__pycache__/
 
^in/
 
^out/
 
\.pyc$
 
^build/
src/diana/config.py
Show inline comments
 
import os
 
from argparse import ArgumentParser
 

	
 

	
 
progName="DianaXO"
 
version=(0,1,0)
 

	
 
curDir=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("-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(progName,*version))
 

	
 
args=parser.parse_args()
 

	
 
inputFiles=[]
 
encoding="utf-8-sig"
 
sgfSuffix=True
 
recursive=False
 
outputDir=curDir
 
outputFormat="svg"
 
keepBroken=False
 

	
 
movesPerDiagram=100
 
minMovesPerDiagram=10
 

	
 

	
 
inputFiles=args.input
 
encoding=args.encoding or "utf-8-sig"
 
sgfSuffix=args.suffix if args.suffix is not None else True
 
recursive=args.recursive
 
outputDir=args.output or curDir
 
outputFormat=args.format or "svg"
 
keepBroken=True if args.keep_broken is not None else False
 
def parseArgs():
 
	global inputFiles,encoding,sgfSuffix,recursive,outputDir,outputFormat,keepBroken,movesPerDiagram
 
	global minMovesPerDiagram
 

	
 
	args=parser.parse_args()
 

	
 
movesPerDiagram=args.moves_p_d or 100
 
minMovesPerDiagram=args.min_p_d or 10
 
	inputFiles=args.input
 
	if args.encoding: encoding=args.encoding
 
	if args.suffix: sgfSuffix=True
 
	if args.recursive: recursive=True
 
	if args.output: outputDir=args.output
 
	if args.format: outputFormat=args.format
 
	if args.keep_broken is not None: keepBroken=True
 

	
 
	if args.moves_p_d: movesPerDiagram=args.moves_p_d
 
	if args.min_p_d: minMovesPerDiagram=args.min_p_d
src/diana/diana.py
Show inline comments
 
import os
 
import re
 

	
 
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
 

	
 

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

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

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

	
 
		i=1
 
		for k in range(0,len(self._moves),cfg.movesPerDiagram):
 
			filename=os.path.join(cfg.outputDir,"{0}-{1}".format(self._shortName,i))
 
			self.createDiagram(k,k+cfg.movesPerDiagram).save(filename,"templ-pleb.svg")
 
			i+=1
 

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

	
 
	def createDiagram(self,start,end):
 
		# initialize the diagram
 
		template=Svg()
 

	
 
		self._setMove(start)
 

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

	
 
		# draw the moves
 
		for k in range(start,end):
 
			if k>=len(self._moves): break
 

	
 
			color,move=self._moves[k]
 
			if move==tuple():
 
				template.overlays.append((k,"pass")) # !!
 
				continue
 
			else:
 
				(c,r)=move
 

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

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

	
 
		return template
 

	
 
	def createGameInfo(self):
 
		rec=self._record
 
		return """{title}
 
B: {black} {bRank}
 
W: {white} {wRank}
 
{date}
 
{result}""".format(title=rec.get("GN",""), black=rec.get("PB",""), bRank=rec.get("BR",""), white=rec.get("PW",""), wRank=rec.get("WR",""), date=rec.get("DT",""), result=rec.get("RE",""))
 
	def fetchGameInfo(self,fieldNames,default=None):
 
		return {k:self._record.get(k,default) for k in fieldNames}
 

	
 
	def _setMove(self,k):
 
		self._game=go.Go()
 

	
 
		blackStones=self._record.root.getProp("AB")
 
		whiteStones=self._record.root.getProp("AW")
 
		if blackStones:
 
			for p in blackStones:
 
				self._game.board[p.c][p.r]=BLACK
 
				self._game.board[p.r][p.c]=BLACK
 
		if whiteStones:
 
			for p in whiteStones:
 
				self._game.board[p.c][p.r]=WHITE
 
				self._game.board[p.r][p.c]=WHITE
 

	
 
		for i in range(k):
 
			(color,move)=self._moves[i]
 
			if move==tuple(): continue # pass
 
			self._move(color,*move)
 

	
 
	def _move(self,color,c,r):
 
		if not self._game.move(BLACK if color=='b' else WHITE, c,r):
 
			# !! 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._game.moveCount+1,c,r)
 
			if cfg.keepBroken:
 
				print(msg)
 
			else:
 
				msg+=". aborted"
 
				print(msg)
 
				return False
 
		return True
 

	
 

	
 
if __name__=="__main__":
 
	cfg.parseArgs()
 
	print("processing:")
 
	files=cfg.inputFiles[:]
 

	
 
	for item in files:
 
		if os.path.isfile(item):
 
			try:
 
				f=SourceFile(item)
 
				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))
0 comments (0 inline, 0 general)