8 ParseError = Class.new(ParseException)
10 def initialize(serializer, state_factory)
11 @serializer = serializer
12 @state_factory = state_factory
15 def write(info, history)
16 date = if info[:date].respond_to? :strftime
17 info[:date].strftime('%Y.%m.%d')
21 tag(:event, info[:event]) +
22 tag(:site, info[:site]) +
24 tag(:round, info[:round]) +
25 player_tags(info[:players] || { }) +
26 tag(:result, result(info[:result])) +
29 result(info[:result]) + "\n"
34 scanner = StringScanner.new(text)
35 while scanner.scan(/\[(.*) "(.*)"\]\n/)
36 info[scanner[1].downcase.to_sym] = scanner[2]
40 # insert players into info[:players]
41 info[:players] = read_players(info)
43 state = @state_factory.new
45 history = History.new(state)
48 while scanner.scan(/(\d+)\.\s*/)
49 if index != scanner[1].to_i
50 raise ParseError.new("Unexpected index #{index}")
53 wmove = @serializer.deserialize(scanner, state)
54 raise ParseError.new("Expected move at index #{index}") unless wmove
57 history.add_move(state, wmove)
60 bmove = @serializer.deserialize(scanner, state)
64 history.add_move(state, bmove)
71 result = scanner.scan(/1-0|0-1|1\/2-1\/2|\*/)
72 info[:result] = result if result
78 %{[#{key.to_s.capitalize} "#{value}"]\n}
84 def read_players(info)
86 :white => info[:white],
87 :black => info[:black] }
93 def player_tags(players)
94 tag(:white, players[:white]) +
95 tag(:black, players[:black])
114 1.to_enum(:step, history.size - 1, 2).map do |i|
115 wmove = @serializer.serialize(history[i].move, history[i - 1].state)
116 bmove = if i + 1 < history.size
117 @serializer.serialize(history[i + 1].move, history[i].state)
120 result = "#{index}.#{wmove}"
121 result += " #{bmove}" if bmove