import os import re import sys 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)) t=sys.stdout 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] def processFile(fileName): print("{0}... ".format(fileName), end="") shortName="".join(re.split(r'[/\\]',fileName)[-1].split('.')[:-1]) game=go.Go() global t try: games=Collection(open(fileName, 'r', encoding=cfg.encoding).read()).listGames() except ParserError as e: print("Couldn't parse {0}, following error occured: {1}".format(fileName,e)) return False record=list(games)[0] moves=list(collectMoves(record)) localBoard=dict() overlays="" letters=dict() letter='a' diagramsNeeded=(len(moves)-cfg.minMovesPerDiagram)//cfg.movesPerDiagram+1 moveNumber=0 for i in range(diagramsNeeded): # initialize the diagram diagram=Svg() for lineNumber,line in enumerate(game.board): for itemNumber,item in enumerate(line): if item==BLACK: diagram.addStone(itemNumber,lineNumber,"b") if item==WHITE: diagram.addStone(itemNumber,lineNumber,"w") localBoard={(a,b):game.board[b][a]-1 for a in range(19) for b in range(19) if game.board[b][a]!=EMPTY} for j in range(cfg.movesPerDiagram): # draw the moves if moveNumber>=len(moves): break c,move=moves[moveNumber] c=c.lower() if move==tuple(): overlays+="{0} pass\n".format(moveNumber) moveNumber+=1 continue else: (x,y)=move if not 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(moveNumber+1,x,y) if cfg.keepBroken: print(msg) 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)]=moveNumber+1 diagram.addMove(x,y,c,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' diagram.addMove(x,y,color,letter) letter=chr(ord(letter)+1) overlays+="{0} = {1}\n".format(moveNumber+1,letters[(x,y)]) # intersection occupied by a numbered stone else: overlays+="{0} = {1}\n".format(moveNumber+1,localBoard[(x,y)]) moveNumber+=1 # finish and save the diagram t=open(os.path.join(cfg.outputDir,"{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # a new file t.write(diagram.render(env.get_template("templ.svg"))) t.close() notes=open(os.path.join(cfg.outputDir,"{0}.txt".format(shortName)),'w') notes.write(overlays) notes.close() print("done") print("processing:") files=cfg.inputFiles[:] for item in files: if os.path.isfile(item): processFile(item) 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))