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 .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() 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(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 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.r][p.c]=BLACK if whiteStones: for p in whiteStones: 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 def 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))