Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

190 linhas
5.9 KiB

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