# HG changeset patch # User Laman # Date 2016-08-13 16:57:58 # Node ID daac513eadcc24546f4f1182cf8a8e8c32ba6cc4 # Parent 3ce489491296f7f86470522b0a1bbb5347996950 another random commit diff --git a/.hgignore b/.hgignore new file mode 100755 --- /dev/null +++ b/.hgignore @@ -0,0 +1,4 @@ +^\. +__pycache__/ +^in/ +^out/ diff --git a/diana.py b/diana.py old mode 100644 new mode 100755 --- a/diana.py +++ b/diana.py @@ -9,21 +9,22 @@ if len(sys.argv)>1: else: sys.exit("no input file specified") -movesPerDiagram=50 +movesPerDiagram=75 minMovesPerDiagram=10 t=sys.stdout c=28 padding=15 -highNumbers=False +highNumbers=True class Svg: content="" footer="" + extension="svg" padding=15 gridSize=28 - highNumbers=False + highNumbers=True def __init__(self): self.content=''' @@ -88,42 +89,45 @@ class Svg: class Tikz: content="" footer="" + extension="tex" - highNumbers=False + highNumbers=True def __init__(self): - self.content='''\\begin{tikzpicture} - \\draw[step=\\boardSquare,gray,very thin] (0,0) grid (18\\boardSquare,18\\boardSquare); - \\draw (0,0) rectangle (18\\boardSquare,18\\boardSquare);\n\n''' + self.content=r'''\begin{tikzpicture} + \draw[step=\boardSquare,gray,very thin] (0,0) grid (18\boardSquare,18\boardSquare); + \draw (0,0) rectangle (18\boardSquare,18\boardSquare); + + ''' # hvězdy for i in range(3): for j in range(3): - self.content+=' \\filldraw[fill=black] ({0}\\boardSquare,{1}\\boardSquare) circle[radius=0.04];\n'.format(6*i+3, 6*j+3) + self.content+=r''' \filldraw[fill=black] ({0}\boardSquare,{1}\boardSquare) circle[radius=0.04];'''.format(6*i+3, 6*j+3)+'\n' self.content+='\n' - self.footer='\\end{tikzpicture}\n' + self.footer=r'\end{tikzpicture}' '\n' def __str__(self): return self.content+self.footer def drawStone(self,x,y,color): fill="black" if color=="b" else "white" - self.content+=' \\filldraw[draw=black,fill={0}] ({1}\\boardSquare,{2}\\boardSquare) circle[radius=0.5\\boardSquare];\n'.format(fill,x,18-y) + self.content+=r' \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare];'.format(fill,x,18-y)+'\n' def drawMove(self,x,y,label,color): fill="black" if color=="b" else "white" labelColor="white" if color=="b" else "black" if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika - self.content+=' \\filldraw[draw=black,fill={0}] ({1}\\boardSquare,{2}\\boardSquare) circle[radius=0.5\\boardSquare] node[color={3}]{{{4}}};\n'.format(fill,x,18-y,labelColor,label) + self.content+=r' \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill,x,18-y,labelColor,label)+'\n' def getContent(self): return self.content+self.footer def processFile(fileName): - shortName="".join(fileName.split('/')[-1].split('.')[:-1]) + shortName="".join(re.split(r'[/\\]',fileName)[-1].split('.')[:-1]) game=go.Go() global t @@ -180,20 +184,24 @@ def processFile(fileName): moveNumber+=1 # dokonči a ulož diagram - t=open("out/{0}-{1}.tex".format(shortName,i+1),'w') # nový soubor + # TODO rozumně pracovat s adresáři + t=open(os.path.join(os.path.dirname(__file__),"out","{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # nový soubor t.write(diagram.getContent()) t.close() - notes=open("out/{0}.txt".format(shortName),'w') + notes=open(os.path.join(os.path.dirname(__file__),"out","{0}.txt".format(shortName)),'w') notes.write(overlays) notes.close() print("processing:") for item in files: + # relativně vůči work directory nebo vůči skriptu? + # item=os.path.join(os.path.dirname(__file__),item) if os.path.isfile(item): - print("{0}... ".format("".join(item.split('/')[-1].split('.')[:-1])),end="") + print("{0}... ".format(item),end="") processFile(item) print("done") 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)) diff --git a/example.lyx b/example.lyx old mode 100644 new mode 100755 diff --git a/go.py b/go.py old mode 100644 new mode 100755 diff --git a/insertMatrix1.lyx b/insertMatrix1.lyx old mode 100644 new mode 100755 diff --git a/notes.txt b/notes.txt old mode 100644 new mode 100755 diff --git a/sgf-compresor.py b/sgf-compresor.py old mode 100644 new mode 100755 diff --git a/sgf.py b/sgf.py old mode 100644 new mode 100755 --- a/sgf.py +++ b/sgf.py @@ -1,45 +1,582 @@ import re -import datetime + + +class Collection: + gameTrees=[] + + def export(self): + res="" + for root in gameTrees: + res+="({0})\n".format(root.fullExport()) + return res + +class Node: + parent=None + children=[] + properties={} + + def newChild(self): + child=Node() + child.parent=self + self.children.append(child) + return child + + def addChild(self,child): + child.parent=self + self.children.append(child) + + def delChild(self,index): + del self.children[index] + + def setProperty(self): pass + def getProperty(self): pass + + def fullExport(self): + res=self.export() + if len(self.children)==1: res+=children[0].fullExport() + else: + for child in self.children: + res+=child.fullExport() + return res + + def export(self): + res=";" + for name,value in properties.items(): + res+="{0}[{1}]".format(name,value) # !! str(value) + res+="\n" + return res + +class Property: + name="" + value=None + +class ListOf(Property): + values=[] + vType=None + + def __str__(self): + return "["+"][".join(self.values)+"]" + +class Composed(Property): + value=() + + def __str__(self): + return self.value[0]+":"+self.value[1] # !! str(self.value[0]) + +class Point(Property): # !! pass + row=0 + col=0 + + def __str__(self): + f=lambda x: chr(x+ord("a")) if x<26 else chr(x-26+ord("A")) + row=f(self.row) + col=f(self.col) + + return col+row + + + +def skipWhitespace(str,start): + i=start + while i=len(str) or str[i]!="(": + # print("error when parsing GameTree") + return (start,None) + i=skipWhitespace(str,i) + i,x=Node.create(str,start+1) + if x is None: + # print("error when parsing GameTree") + return (i,None) + while x is not None: + res.nodes.append(x) + i=skipWhitespace(str,i) + i,x=Node.create(str,i) + i=skipWhitespace(str,i) + i,x=GameTree.create(str,i) + while x is not None: + res.branches.append(x) + i=skipWhitespace(str,i) + i,x=GameTree.create(str,i) + if str[i]!=")": + # print("error when parsing GameTree") + return (i,None) + return (i+1,res) + +class Node: + properties=dict() + + def create(str,start): + res=Node() + if str[start]!=";": + # print("error when parsing Node") + return (start,None) + i=skipWhitespace(str,start+1) + i,x=Property.create(str,i) + while x is not None: + if x.name in res.properties: + print('error: duplicate "{0}" property in node at position {1}. second value ignored'.format(x.name,start)) + else: + res.properties[x.name]=x + i=skipWhitespace(str,i) + i,x=Property.create(str,i) + return (i,res) + + def setProperty(self,name,value): + self.properties[name]=value + # zkontrolovat typ value + + def getProperty(self,name): + if name in self.properties: return self.properties[name] + else: return None + +class Property: + name="" + value="" - result=None - komi=6.5 + def create(str,start): + res=Property() + i,x=Property.ident(str,start) + if x is None: + return (start,None) + res.name=x + i,x=PropValue.create(str,i,res.name) + if x is None: + print('error when parsing property "{0}" at position {1}'.format(res.name,i)) + return (start,None) + # while x is not None: # přesunuto do PropValue.listOf + # res.values.append(x) + # i=skipWhitespace(str,i) + # i,x=PropValue.create(str,i,res.name) + res.values.append(x) # !! podezřelé + return (i,res) + + def ident(str,start): + r=re.compile(r"[A-Z]+") + m=r.match(str,start) + if m is None: return (start,None) + return (m.end(),m.group()) + +class PropValue: + type="" + value=None + patterns=dict() + + def create(str,start,name): + if name in PropValue.patterns: + return PropValue.patterns[name](str,start) + else: + print('warning, unknown property "{0}" at position {1}'.format(name,start)) + return PropValue.singleton(PropValue.anything)(str,start) + + # def singleton(str,start,vType): + # if str[start]!="[": + # return (start,None) + # i,x=vType(str,start+1) + # if x is None: return (start,None) + # if str[i]!="]": + # return (start,None) + # return (i+1,x) + + def choose(*vTypes): + def f(str,start): + for vType in vTypes: + i,x=vType(str,start) + if x is not None: return (i,x) + return (start,None) + return f - date=None - place=None + def singleton(vType): + def f(str,start): + if str[start]!="[": + return (start,None) + i,x=vType(str,start+1) + if x is None: return (start,None) + if str[i]!="]": + return (start,None) + return (i+1,x) + return f + + # def listOf(str,start,vType,allowEmpty=False): + # res=[] + # i,x=singleton(str,start,vType) + # # singleton(vType) if vType not tuple else compose(vType[0],vType[1]) + # while x!=None: + # res.append(x) + # i,x=singleton(str,i,vType) + # if len(res)==0 and not allowEmpty: return (start,None) + # return (i,res) + + def listOf(vType,allowEmpty=False): + def f(str,start): + res=[] + single=singleton(vType) + i,x=single(str,start) + while x!=None: + res.append(x) + i,x=single(str,i) + if len(res)==0 and not allowEmpty: return (start,None) + return (i,res) + return f + + # def compose(str,start,vTypeA,vTypeB): + # i,a=vTypeA(str,start) + # if a==None or str[i]!=":": return (start,None) + # i,b=vTypeB(str,i+1) + # if b==None: return start,None + # return (i,(a,b)) + + def compose(vTypeA,vTypeB): + def f(str,start): + i,a=vTypeA(str,start) + # print(">",i,a) + if a==None or str[i]!=":": return (start,None) + i,b=vTypeB(str,i+1) + # print(">",i,b) + if b==None: return start,None + return (i,(a,b)) + return f - moves=[] + def number(str,start): + r=re.compile(r"(\+|-|)\d+") + m=r.match(str,start) + if m is None: return (start,None) + res=int(m.group(0)) + return (m.end(),res) + + def real(str,start): + r=re.compile(r"(\+|-|)\d+(\.\d+)?") + m=r.match(str,start) + if m is None: return (start,None) + res=float(m.group(0)) + return (m.end(),res) + + def double(str,start): + r=re.compile(r"1|2") + m=r.match(str,start) + if m is None: return (start,None) + res=int(m.group(0)) + return (m.end(),res) - def __init__(self,s): - m=re.search("GN\[.*\]",s) - if m: self.gameName=m.group() - m=re.search("PB\[.*\]",s) - if m: self.black=m.group() - m=re.search("PW\[.*\]",s) - if m: self.white=m.group() - m=re.search("BR\[.*\]",s) - if m: self.rankB=m.group() - m=re.search("WR\[.*\]",s) - if m: self.rankW=m.group() - m=re.search("RE\[.*\]",s) - if m: self.result=m.group() - m=re.search("KM\[.*\]",s) - if m: self.komi=m.group() - m=re.search("PC\[.*\]",s) - if m: self.place=m.group() - m=re.search("DT\[.*\]",s) - if m: self.date=m.group() # naparsovat ho + def color(str,start): + r=re.compile(r"B|W") + m=r.match(str,start) + if m is None: return (start,None) + return (m.end(),m.group(0)) + + # def simpleText(str,start): + # res="" + # esc=False + # lineBreak=False + # for c in str: + # if esc: + # res+=c + # esc=False + # elif c=="\\": + # esc=True + # elif c=="]": + # break + # else: + # res+=c + # return res + + def text(simple=True,composed=False): + def f(str,start): + res="" + esc=False + lastC="" + for i,c in enumerate(str[start:],start): + if esc: + if c!="\n" and c!="\r": res+=c + esc=False + elif (c=="\n" and lastC=="\r") or (c=="\r" and lastC=="\n"): pass + elif c=="\r" or c=="\n" and not simple: + res+="\n" + elif c.isspace(): + res+=" " + elif c=="\\": + esc=True + elif c=="]" or (c==":" and composed): + break + else: + res+=c + lastC=c + return (i,res) + return f + + def empty(str,start): return (start,"") + + def anything(str,start): # přidat listOf + esc=False + for i,c in enumerate(str[start:],start): + if esc: esc=False + elif c=="\\": esc=True + elif c=="]": break + return (i,str[start:i]) + + # go specific + def point(str,start): + r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size + m=r.match(str,start) + if m is None: return (start,None) + if m.group(0)=="": # pass, !! tt + return (m.end(),tuple()) + col=m.group(0)[0] + row=m.group(0)[1] + col=ord(col) - (ord("a") if "a"<=col<="z" else ord("A")-26) + row=ord(row) - (ord("a") if "a"<=row<="z" else ord("A")-26) + return (m.end(),(col,row)) + + move=point + stone=point + + patterns={ + "B":singleton(move), + "KO":singleton(empty), + "MN":singleton(number), + "W":singleton(move), + "AB":listOf(stone), # + "AE":listOf(point), # + "AW":listOf(stone), # + "PL":singleton(color), + "C":singleton(text(simple=False)), + "DM":singleton(double), + "GB":singleton(double), + "GW":singleton(double), + "HO":singleton(double), + "N":singleton(text()), + "UC":singleton(double), + "V":singleton(real), + "BM":singleton(double), + "DO":singleton(empty), + "IT":singleton(empty), + "TE":singleton(double), + "AR":listOf(compose(point,point)), # + "CR":listOf(point), # + "DD":listOf(point,allowEmpty=True), # + "LB":listOf(compose(point,text())), # + "LN":listOf(compose(point,point)), # + "MA":listOf(point), # + "SL":listOf(point), # + "SQ":listOf(point), # + "TR":listOf(point), # + "AP":singleton(compose(text(composed=True),text())), # + "CA":singleton(text()), + "FF":singleton(number), + "GM":singleton(number), + "ST":singleton(number), + "SZ":choose(singleton(number),singleton(compose(number,number))), # + "AN":singleton(text()), + "BR":singleton(text()), + "BT":singleton(text()), + "CP":singleton(text()), + "DT":singleton(text()), + "EV":singleton(text()), + "GN":singleton(text()), + "GC":singleton(text(simple=False)), + "ON":singleton(text()), + "OT":singleton(text()), + "PB":singleton(text()), + "PC":singleton(text()), + "PW":singleton(text()), + "RE":singleton(text()), + "RO":singleton(text()), + "RU":singleton(text()), + "SO":singleton(text()), + "TM":singleton(real), + "US":singleton(text()), + "WR":singleton(text()), + "WT":singleton(text()), + "BL":singleton(real), + "OB":singleton(number), + "OW":singleton(number), + "WL":singleton(real), + "FG":choose(singleton(empty),singleton(compose(number,text()))), # + "PM":singleton(number), + "VW":listOf(point,allowEmpty=True), # - self.moves=re.findall("\W([BW])\[([a-s]{2})\]",s) # a pass? - char2int=lambda a:ord(a)-ord('a') - self.moves=[(c,(char2int(m[0]),char2int(m[1]))) for c,m in self.moves] + # go specific + "HA":singleton(number), + "KM":singleton(real), + "TB":listOf(point,allowEmpty=True), + "TW":listOf(point,allowEmpty=True) + } + +"""def property(str): + # i=propIdent(str) + # if i<0: return -1 + # j=i + # i=propValue(str[i:]) + # while i>=0: + # j+=i + # i=propValue(str[i:]) + # return j + +def propIdent(str): + m=re.match(r"[A-Z]+",str) + if m is None: return -1 + return m.end() + +def propValue(str): + i=cValueType(str[1:]) + if str[0]=="[" and i>=0 and str[i]=="]": return i+1 + else: return -1 + +class propValue: + pass + +def cValueType(str,start): + matches=[real,number,double,color,simpleText] + for f in matches: + i,x=f(str,start) + if x is not None: return i,x + return 1/0 + +def number(str,start): + r=re.compile(r"(\+|-|)\d+") + m=r.match(str,start) + if m is None: return (-1,None) + x=int(m.group(0)) + return (m.end(),x) + +def real(str): + m=re.match(r"(\+|-|)\d+(\.\d+)?",str) + if m is None: return -1 + return m.end() + +def double(str): + m=re.match(r"1|2",str) + if m is None: return -1 + return m.end() + +def color(str): + m=re.match(r"B|W",str) + if m is None: return -1 + return m.end() - def getMoves(self): - return self.moves.copy() - \ No newline at end of file +def simpleText(str): + res=r"" + esc=False + for c in str: + if esc: + res+=c + esc=False + elif c=="\\": + esc=True + elif c=="]": + break + else: + res+=c + return res""" + +sgf=open("in/1-Hora-Simara.sgf").read() + +x=Collection(sgf) + +# TODO: +# date + + +""" +# move +B move +KO none +MN number +W move + +# setup +AB list of stone +AE list of point +AW list of stone +PL color + +# node annotation +C text +DM double +GB double +GW double +HO double +N simpleText +UC double +V real + +# move annotation +BM double +DO none +IT none +TE double + +# markup +AR list of composed point:point +CR list of point +DD elist of point +LB list of composed point:simpleText +LN list of composed point:point +MA list of point +SL list of point +SQ list of point +TR list of point + +# root +AP composed simpleText:simpleText +CA simpleText +FF number +GM number +ST number +SZ number | composed number:number + +# game info +AN simpleText +BR simpleText +BT simpleText +CP simpleText +DT simpleText +EV simpleText +GN simpleText +GC text +ON simpleText +OT simpleText +PB simpleText +PC simpleText +PW simpleText +RE simpleText +RO simpleText +RU simpleText +SO simpleText +TM real +US simpleText +WR simpleText +WT simpleText + +# timing +BL real +OB number +OW number +WL real + +# misc +FG none | composition of number:simpleText +PM number +VW elist of point +""" \ No newline at end of file diff --git a/sgfParser.py b/sgfParser.py old mode 100644 new mode 100755 --- a/sgfParser.py +++ b/sgfParser.py @@ -1,7 +1,4 @@ import re - -# def digit(str): - # if re.match("") str[0] def skipWhitespace(str,start): i=start @@ -86,6 +83,14 @@ class Node: i=skipWhitespace(str,i) i,x=Property.create(str,i) return (i,res) + + def setProperty(self,name,value): + self.properties[name]=value + # zkontrolovat typ value + + def getProperty(self,name): + if name in self.properties: return self.properties[name] + else: return None class Property: name="" diff --git a/work.lyx b/work.lyx old mode 100644 new mode 100755 diff --git a/work2.lyx b/work2.lyx old mode 100644 new mode 100755 diff --git a/work2.tex b/work2.tex old mode 100644 new mode 100755