Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

187 wiersze
5.8 KiB

  1. import argparse
  2. import os
  3. import sys
  4. from subprocess import check_call, DEVNULL, STDOUT, CalledProcessError
  5. from shutil import copyfile, rmtree
  6. from pprint import pprint
  7. import simpleGoBoard
  8. parser = argparse.ArgumentParser(description='Convert sgf go records into a kifu format.')
  9. parser.add_argument('sgfFile')
  10. parser.add_argument('-se', "--splitevery", dest="step", type=int, default=50)
  11. parser.add_argument('-cn', "--continuousNumbers", action="store_true", dest="cn", default=False)
  12. parser.add_argument('-t', "--texOnly", action="store_true", dest="t", default=False)
  13. parser.add_argument('-o', "--open", action="store_true", dest="o", default=False)
  14. args = parser.parse_args(sys.argv[1:])
  15. filePath = args.sgfFile
  16. fileBase = ".".join(filePath.split(".")[:-1])
  17. splitBoardAt = [x for x in range(0, 400, args.step)]
  18. with open(filePath, 'r') as myfile:
  19. sgfData = myfile.read().replace("\n", "").split(";")[1:]
  20. sgfData[-1] = sgfData[-1][:-1]
  21. header = sgfData[0]
  22. moves = sgfData[1:]
  23. def format_date(date):
  24. if date == "":
  25. return ""
  26. months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
  27. ds = date.split("-") # year month day
  28. ds.reverse()
  29. ds[1] = months[int(ds[1])-1]
  30. return " ".join(ds)
  31. def get_tag_from_header(tag):
  32. eventIdxStart = header.lower().find(f"{tag.lower()}[")
  33. eventIdxEnd = -1
  34. if eventIdxStart != -1 :
  35. eventIdxEnd = header.find("]", eventIdxStart)
  36. return header[len(tag) + 1 + eventIdxStart:eventIdxEnd]
  37. return ""
  38. def extract_coordinates(move):
  39. try:
  40. firstCoordinate = move[2]
  41. secondCoordinate = ord(move[3])-96
  42. # mirror at x axis so it looks normal
  43. secondCoordinate = parsedHeader["boardSize"] - secondCoordinate + 1
  44. if ord(move[2]) >= ord("i"):
  45. firstCoordinate = chr(ord(firstCoordinate) + 1)
  46. return firstCoordinate, secondCoordinate
  47. except IndexError:
  48. # wierd move
  49. return -1,-1
  50. def generate_title():
  51. out = []
  52. if parsedHeader["event"] != "":
  53. out.extend([parsedHeader["event"], "\\\\"])
  54. out.append(parsedHeader["playerBlack"])
  55. if parsedHeader["rankBlack"] != "":
  56. out.extend(["[", parsedHeader["rankBlack"], "]"])
  57. out.extend([" - ", parsedHeader["playerWhite"]])
  58. if parsedHeader["rankWhite"] != "":
  59. out.extend(["[", parsedHeader["rankWhite"], "]"])
  60. return "".join(out)
  61. def init_simpleGoBoard():
  62. for move in moves:
  63. if len(move) == 5:
  64. coordinates = (ord(move[2].lower())-ord("a")+1, parsedHeader["boardSize"]-ord(move[3].lower())+ord("a"))
  65. if move[0].lower() == "w":
  66. simpleGoBoard.whiteMoves.append(coordinates)
  67. elif move[0].lower() == "b":
  68. simpleGoBoard.blackMoves.append(coordinates)
  69. def generate_boards():
  70. init_simpleGoBoard()
  71. outText = []
  72. for i in range(len(splitBoardAt)-1):
  73. currentSplit = splitBoardAt[i]
  74. nextSplit = splitBoardAt[i+1]
  75. board, finished = simpleGoBoard.produce_latex(currentSplit, nextSplit, args.cn)
  76. outText.extend(board)
  77. if finished:
  78. break
  79. return "".join(outText)
  80. parsedHeader = {
  81. "event" : get_tag_from_header("EV"),
  82. "gameName" : get_tag_from_header("GN"),
  83. "date" : get_tag_from_header("DT"),
  84. "boardSize" : int(get_tag_from_header("SZ")),
  85. "playerBlack" : get_tag_from_header("PB"),
  86. "playerWhite" : get_tag_from_header("PW"),
  87. "rankBlack" : get_tag_from_header("BR"),
  88. "rankWhite" : get_tag_from_header("WR"),
  89. "komi" : get_tag_from_header("KM"),
  90. "result" : get_tag_from_header("RE")
  91. }
  92. # title = generate_title()
  93. event = parsedHeader["event"]
  94. gameName = parsedHeader["gameName"]
  95. date = format_date(parsedHeader["date"])
  96. result = parsedHeader["result"]
  97. komi = parsedHeader["komi"]
  98. playerWhite = parsedHeader["playerWhite"]
  99. playerBlack = parsedHeader["playerBlack"]
  100. if parsedHeader["rankBlack"] != "":
  101. playerBlack += f" ({parsedHeader['rankBlack']})"
  102. if parsedHeader["rankWhite"] != "":
  103. playerWhite += f" ({parsedHeader['rankWhite']})"
  104. boards = generate_boards()
  105. outText = f"""
  106. \\documentclass[a4paper]{{article}}
  107. \\usepackage{{psgo}}
  108. \\usepackage[ngerman]{{babel}}
  109. \\usepackage[margin=2cm,nohead]{{geometry}}
  110. \\usepackage{{tabularx}}
  111. \\newcolumntype{{R}}{{>{{\\raggedleft\\arraybackslash}}X}}
  112. \\setgounit{{0.5cm}}
  113. \\setcounter{{gomove}}{{0}}
  114. \\begin{{document}}
  115. \\sffamily
  116. \\def\\arraystretch{{2}}
  117. \\begin{{center}}
  118. \\vspace*{{1cm}}
  119. {{\\Huge {event} \\par}}
  120. \\vspace{{0.6cm}}
  121. {{\\huge {gameName} \\par}}
  122. \\vspace{{0.6cm}}
  123. {{\\Large {date} \\par}}
  124. \\vspace{{2cm}}
  125. \\begin{{tabularx}}{{\\textwidth}}{{ R | c | X }}
  126. \\hline
  127. \\stone{{black}} {playerBlack} & \\textbf{{{result}}} & {playerWhite} \\stone{{white}} \\\\\\hline
  128. & {komi} Komi & \\\\\\hline
  129. \\end{{tabularx}}
  130. \\vspace{{3cm}}
  131. {boards}
  132. \\end{{center}}
  133. \\end{{document}}
  134. """
  135. with open(f"{fileBase}.tex", 'w') as outFile:
  136. outFile.write(outText)
  137. # should be compiled to pdf?
  138. if not args.t:
  139. try:
  140. os.makedirs(os.path.dirname(f"{fileBase}/"), exist_ok=True)
  141. copyfile(f"{fileBase}.tex", f"{fileBase}/temp.tex")
  142. os.remove(f"{fileBase}.tex") # poor mans `move` that works on win and linux
  143. check_call(['latex', f"temp.tex"],
  144. stdout=DEVNULL, stderr=STDOUT, cwd=f'{fileBase}')
  145. check_call(['dvips', f"temp.dvi", "-P", "pdf"],
  146. stdout=DEVNULL, stderr=STDOUT, cwd=f'{fileBase}')
  147. check_call(['ps2pdf', f"temp.ps"],
  148. stdout=DEVNULL, stderr=STDOUT, cwd=f'{fileBase}')
  149. except CalledProcessError:
  150. print("error")
  151. else:
  152. copyfile(f"{fileBase}/temp.pdf", f"{fileBase}.pdf")
  153. rmtree(f"{fileBase}/")
  154. # hould output be opened?
  155. if args.o:
  156. os.startfile(f'"{fileBase}.pdf"')