| 252 | DRAW_JS = DRAW_JS |
| 253 | |
| 254 | def parse(self, raw: bytes, players=None) -> ReplayData: |
| 255 | pgn = raw.decode(errors="replace") |
| 256 | white = _header(pgn, "White") or "White" |
| 257 | black = _header(pgn, "Black") or "Black" |
| 258 | result = _header(pgn, "Result") or "*" |
| 259 | |
| 260 | board = _clone(START) |
| 261 | frames = [{"turn": 0, "board": _clone(board), "from": None, "to": None}] |
| 262 | ep = None |
| 263 | turn_white = True |
| 264 | for ply, san in enumerate(_movetext(pgn), start=1): |
| 265 | try: |
| 266 | board, frm, to, ep = _apply(board, san, turn_white, ep) |
| 267 | except Exception: |
| 268 | break # malformed / unexpected token — stop where we are |
| 269 | frames.append({"turn": ply, "board": _clone(board), "from": list(frm), "to": list(to)}) |
| 270 | turn_white = not turn_white |
| 271 | |
| 272 | if result == "1-0": |
| 273 | winner, draw = white, False |
| 274 | elif result == "0-1": |
| 275 | winner, draw = black, False |
| 276 | elif result == "1/2-1/2": |
| 277 | winner, draw = None, True |
| 278 | else: |
| 279 | winner, draw = None, False |
| 280 | |
| 281 | return ReplayData( |
| 282 | w=8, h=8, frames=frames, winner=winner, draw=draw, extra={"names": {"white": white, "black": black}} |
| 283 | ) |