lib/jkf/parser/csa.rb in jkf-0.5.0 vs lib/jkf/parser/csa.rb in jkf-0.5.1

- old
+ new

@@ -1,817 +1,814 @@ -# coding: utf-8 +module Jkf + module Parser + # CSA Parser + class Csa < Base + protected -module Jkf::Parser - # CSA Parser - class Csa < Base - protected + # kifu : csa2 | csa1 + def parse_root + @scanner << "\n" unless @scanner.string[-1] =~ /\n|\r|,/ # FIXME + s0 = parse_csa2 + s0 = parse_csa1 if s0 == :failed + s0 + end - # kifu : csa2 | csa1 - def parse_root - @input += "\n" unless @input[-1] =~ /\n|\r|,/ # FIXME - s0 = parse_csa2 - s0 = parse_csa1 if s0 == :failed - s0 - end + # csa2 : version22 information? initialboard moves? + def parse_csa2 + s0 = @scanner.pos + if parse_version22 == :failed + @scanner.pos = s0 + s0 = :failed + else + s1 = parse_information + s1 = nil if s1 == :failed + s2 = parse_initial_board + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + s3 = parse_moves + s3 = nil if s3 == :failed + @reported_pos = s0 + s0 = -> (info, ini, ms) do + ret = { 'header' => info['header'], 'initial' => ini, 'moves' => ms } + if info && info['players'] + ret['header']['先手'] = info['players'][0] if info['players'][0] + ret['header']['後手'] = info['players'][1] if info['players'][1] + end + ret + end.call(s1, s2, s3) + end + end + s0 + end - # csa2 : version22 information? initialboard moves? - def parse_csa2 - s0 = @current_pos - if parse_version22 == :failed - @current_pos = s0 - s0 = :failed - else - s1 = parse_information - s1 = nil if s1 == :failed - s2 = parse_initial_board + # version22 : comment* "V2.2" nl + def parse_version22 + s0 = @scanner.pos + s1 = parse_comments + s2 = match_str('V2.2') if s2 == :failed - @current_pos = s0 + @scanner.pos = s0 s0 = :failed else - s3 = parse_moves - s3 = nil if s3 == :failed - @reported_pos = s0 - s0 = -> (info, ini, ms) do - ret = { "header" => info["header"], "initial" => ini, "moves" => ms } - if info && info["players"] - ret["header"]["先手"] = info["players"][0] if info["players"][0] - ret["header"]["後手"] = info["players"][1] if info["players"][1] - end - ret - end.call(s1, s2, s3) + s3 = parse_nl + if s3 == :failed + @scanner.pos = s0 + s0 = :failed + else + s0 = [s1, s2, s3] + end end + s0 end - s0 - end - # version22 : comment* "V2.2" nl - def parse_version22 - s0 = @current_pos - s1 = parse_comments - s2 = match_str("V2.2") - if s2 == :failed - @current_pos = s0 - s0 = :failed - else - s3 = parse_nl - if s3 == :failed - @current_pos = s0 + # information : players? headers + def parse_information + s0 = @scanner.pos + s1 = parse_players + s1 = nil if s1 == :failed + s2 = parse_headers + if s2 == :failed + @scanner.pos = s0 s0 = :failed else - s0 = [s1, s2, s3] + @reported_pos = s0 + s0 = { 'players' => s1, 'header' => s2 } end + s0 end - s0 - end - # information : players? headers - def parse_information - s0 = @current_pos - s1 = parse_players - s1 = nil if s1 == :failed - s2 = parse_headers - if s2 == :failed - @current_pos = s0 - s0 = :failed - else + # headers : header* + def parse_headers + s0 = @scanner.pos + s1 = [] + s2 = parse_header + while s2 != :failed + s1 << s2 + s2 = parse_header + end @reported_pos = s0 - s0 = { "players" => s1, "header" => s2 } + -> (header) do + ret = {} + header.each do |data| + ret[normalize_header_key(data['k'])] = data['v'] + end + ret + end.call(s1) end - s0 - end - # headers : header* - def parse_headers - s0 = @current_pos - s1 = [] - s2 = parse_header - while s2 != :failed - s1 << s2 - s2 = parse_header - end - @reported_pos = s0 - s0 = -> (header) do - ret = {} - header.each do |data| - ret[normalize_header_key(data["k"])] = data["v"] - end - ret - end.call(s1) - s0 - end - - # header : comment* "$" [^:]+ ":" nonls nl - def parse_header - s0 = @current_pos - parse_comments - if match_str("$") == :failed - @current_pos = s0 - s0 = :failed - else - s4 = match_regexp(/^[^:]/) - if s4 == :failed - s3 = :failed + # header : comment* "$" [^:]+ ":" nonls nl + def parse_header + s0 = @scanner.pos + parse_comments + if match_str('$') == :failed + @scanner.pos = s0 + s0 = :failed else - s3 = [] - while s4 != :failed - s3 << s4 - s4 = match_regexp(/^[^:]/) + s4 = match_regexp(/[^:]/) + if s4 == :failed + s3 = :failed + else + s3 = [] + while s4 != :failed + s3 << s4 + s4 = match_regexp(/[^:]/) + end end - end - if s3 == :failed - @current_pos = s0 - s0 = :failed - elsif match_str(":") != :failed - s4 = parse_nonls - if parse_nl == :failed - @current_pos = s0 + if s3 == :failed + @scanner.pos = s0 s0 = :failed + elsif match_str(':') != :failed + s4 = parse_nonls + if parse_nl == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = { 'k' => s3.join, 'v' => s4.join } + end else - @reported_pos = s0 - s0 = { "k" => s3.join, "v" => s4.join } + @scanner.pos = s0 + s0 = :failed end - else - @current_pos = s0 - s0 = :failed end + s0 end - s0 - end - # csa1 : players? initialboard? moves - def parse_csa1 - s0 = @current_pos - s1 = parse_players - s1 = nil if s1 == :failed - s2 = parse_initial_board - s2 = nil if s2 == :failed - s3 = parse_moves - if s3 == :failed - @current_pos = s0 - s0 = :failed - else - @reported_pos = s0 - s0 = -> (ply, ini, ms) do - ret = { "header" => {}, "initial" => ini, "moves" => ms } - if ply - ret["header"]["先手"] = ply[0] if ply[0] - ret["header"]["後手"] = ply[1] if ply[1] - end - ret - end.call(s1, s2, s3) + # csa1 : players? initialboard? moves + def parse_csa1 + s0 = @scanner.pos + s1 = parse_players + s1 = nil if s1 == :failed + s2 = parse_initial_board + s2 = nil if s2 == :failed + s3 = parse_moves + if s3 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = -> (ply, ini, ms) do + ret = { 'header' => {}, 'initial' => ini, 'moves' => ms } + if ply + ret['header']['先手'] = ply[0] if ply[0] + ret['header']['後手'] = ply[1] if ply[1] + end + ret + end.call(s1, s2, s3) + end + s0 end - s0 - end - # players : comment* ("N+" nonls nl)? comment* ("N-" nonls nl)? - def parse_players - s0 = @current_pos - parse_comments - s2 = @current_pos - if match_str("N+") == :failed - @current_pos = s2 - s2 = :failed - else - s4 = parse_nonls - if parse_nl == :failed - @current_pos = s2 + # players : comment* ("N+" nonls nl)? comment* ("N-" nonls nl)? + def parse_players + s0 = @scanner.pos + parse_comments + s2 = @scanner.pos + if match_str('N+') == :failed + @scanner.pos = s2 s2 = :failed else - @reported_pos = s2 - s2 = s4 + s4 = parse_nonls + if parse_nl == :failed + @scanner.pos = s2 + s2 = :failed + else + @reported_pos = s2 + s2 = s4 + end end - end - s2 = nil if s2 == :failed - parse_comments - s4 = @current_pos - if match_str("N-") == :failed - @current_pos = s4 - s4 = :failed - else - s6 = parse_nonls - if parse_nl == :failed - @current_pos = s4 + s2 = nil if s2 == :failed + parse_comments + s4 = @scanner.pos + if match_str('N-') == :failed + @scanner.pos = s4 s4 = :failed else - @reported_pos = s4 - s4 = s6 + s6 = parse_nonls + if parse_nl == :failed + @scanner.pos = s4 + s4 = :failed + else + @reported_pos = s4 + s4 = s6 + end end + s4 = nil if s4 == :failed + @reported_pos = s0 + [s2&.join, s4&.join] end - s4 = nil if s4 == :failed - @reported_pos = s0 - s0 = [(s2 ? s2.join : nil), (s4 ? s4.join : nil)] - s0 - end - # initialboard : comment* (hirate | ikkatsu | "") komabetsu comment* teban nl - def parse_initial_board - s0 = @current_pos - parse_comments - s2 = parse_hirate - if s2 == :failed - s2 = parse_ikkatsu + # initialboard : comment* (hirate | ikkatsu | "") komabetsu comment* teban nl + def parse_initial_board + s0 = @scanner.pos + parse_comments + s2 = parse_hirate if s2 == :failed - s2 = @current_pos - s3 = match_str("") - if s3 != :failed - @reported_pos = s2 - s3 = "NO" + s2 = parse_ikkatsu + if s2 == :failed + s2 = @scanner.pos + s3 = match_str('') + if s3 != :failed + @reported_pos = s2 + s3 = 'NO' + end + s2 = s3 end - s2 = s3 end - end - if s2 == :failed - @current_pos = s0 - :failed - else - s3 = parse_komabetsu - if s3 == :failed - @current_pos = s0 + if s2 == :failed + @scanner.pos = s0 :failed else - parse_comments - s5 = parse_teban - if s5 == :failed - @current_pos = s0 + s3 = parse_komabetsu + if s3 == :failed + @scanner.pos = s0 :failed - elsif parse_nl != :failed - @reported_pos = s0 - -> (data, koma, teban) do - if data == "NO" - data = koma - else - data["data"]["hands"] = koma["data"]["hands"] - end - data["data"]["color"] = teban - data - end.call(s2, s3, s5) else - @current_pos = s0 - :failed + parse_comments + s5 = parse_teban + if s5 == :failed + @scanner.pos = s0 + :failed + elsif parse_nl != :failed + @reported_pos = s0 + -> (data, koma, teban) do + if data == 'NO' + data = koma + else + data['data']['hands'] = koma['data']['hands'] + end + data['data']['color'] = teban + data + end.call(s2, s3, s5) + else + @scanner.pos = s0 + :failed + end end end end - end - # hirate : "PI" xypiece* nl - def parse_hirate - s0 = @current_pos - if match_str("PI") == :failed - @current_pos = s0 - s0 = :failed - else - s2 = [] - s3 = parse_xy_piece - while s3 != :failed - s2 << s3 - s3 = parse_xy_piece - end - if parse_nl == :failed - @current_pos = s0 + # hirate : "PI" xypiece* nl + def parse_hirate + s0 = @scanner.pos + if match_str('PI') == :failed + @scanner.pos = s0 s0 = :failed else - @reported_pos = s0 - s0 = -> (ps) do - ret = { "preset" => "OTHER", "data" => { "board" => get_hirate } } - ps.each do |piece| - ret["data"]["board"][piece["xy"]["x"] - 1][piece["xy"]["y"] - 1] = {} - end - ret - end.call(s2) - end - end - s0 - end - - # ikkatsu : ikkatsuline+ - def parse_ikkatsu - s0 = @current_pos - s2 = parse_ikkatsu_line - if s2 == :failed - s1 = :failed - else - s1 = [] - while s2 != :failed - s1 << s2 - s2 = parse_ikkatsu_line - end - end - if s1 != :failed - @reported_pos = s0 - s1 = -> (lines) do - board = [] - 9.times do |i| - line = [] - 9.times do |j| - line << lines[j][8 - i] - end - board << line + s2 = [] + s3 = parse_xy_piece + while s3 != :failed + s2 << s3 + s3 = parse_xy_piece end - { "preset" => "OTHER", "data" => { "board" => board } } - end.call(s1) - end - s0 = s1 - s0 - end - - # ikkatsuline : "P" [1-9] masu+ nl - def parse_ikkatsu_line - s0 = @current_pos - if match_str("P") == :failed - @current_pos = s0 - s0 = :failed - elsif match_digit != :failed - s4 = parse_masu - if s4 == :failed - s3 = :failed - else - s3 = [] - while s4 != :failed - s3 << s4 - s4 = parse_masu - end - end - if s3 == :failed - @current_pos = s0 - s0 = :failed - else - s4 = parse_nl - if s4 == :failed - @current_pos = s0 + if parse_nl == :failed + @scanner.pos = s0 s0 = :failed else @reported_pos = s0 - s0 = s3 + s0 = -> (ps) do + ret = { 'preset' => 'OTHER', 'data' => { 'board' => hirate } } + ps.each do |piece| + ret['data']['board'][piece['xy']['x'] - 1][piece['xy']['y'] - 1] = {} + end + ret + end.call(s2) end end - else - @current_pos = s0 - s0 = :failed + s0 end - s0 - end - # masu : teban piece | " * " - def parse_masu - s0 = @current_pos - s1 = parse_teban - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = parse_piece + # ikkatsu : ikkatsuline+ + def parse_ikkatsu + s0 = @scanner.pos + s2 = parse_ikkatsu_line if s2 == :failed - @current_pos = s0 - s0 = :failed + s1 = :failed else - @reported_pos = s0 - s0 = { "color" => s1, "kind" => s2 } + s1 = [] + while s2 != :failed + s1 << s2 + s2 = parse_ikkatsu_line + end end - end - if s0 == :failed - s0 = @current_pos - if match_str(" * ") != :failed + if s1 != :failed @reported_pos = s0 - s1 = {} + s1 = -> (lines) do + board = [] + 9.times do |i| + line = [] + 9.times do |j| + line << lines[j][8 - i] + end + board << line + end + { 'preset' => 'OTHER', 'data' => { 'board' => board } } + end.call(s1) end - s0 = s1 + s1 end - s0 - end - # komabetsu : komabetsuline* - def parse_komabetsu - s0 = @current_pos - s1 = [] - s2 = parse_komabetsu_line - while s2 != :failed - s1 << s2 - s2 = parse_komabetsu_line - end - @reported_pos = s0 - transform_komabetsu_lines(s1) - end - - # komabetsuline : "P" teban xypiece+ nl - def parse_komabetsu_line - s0 = @current_pos - if match_str("P") == :failed - @current_pos = s0 - s0 = :failed - else - s2 = parse_teban - if s2 == :failed - @current_pos = s0 + # ikkatsuline : "P" [1-9] masu+ nl + def parse_ikkatsu_line + s0 = @scanner.pos + if match_str('P') == :failed + @scanner.pos = s0 s0 = :failed - else - s4 = parse_xy_piece + elsif match_digit != :failed + s4 = parse_masu if s4 == :failed s3 = :failed else s3 = [] while s4 != :failed s3 << s4 - s4 = parse_xy_piece + s4 = parse_masu end end if s3 == :failed - @current_pos = s0 + @scanner.pos = s0 s0 = :failed - elsif parse_nl != :failed - @reported_pos = s0 - s0 = { "teban" => s2, "pieces" => s3 } else - @current_pos = s0 - s0 = :failed + s4 = parse_nl + if s4 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = s3 + end end + else + @scanner.pos = s0 + s0 = :failed end + s0 end - s0 - end - # moves : firstboard move* comment* - def parse_moves - s0 = @current_pos - s1 = parse_firstboard - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = [] - s3 = parse_move - while s3 != :failed - s2 << s3 - s3 = parse_move + # masu : teban piece | " * " + def parse_masu + s0 = @scanner.pos + s1 = parse_teban + if s1 == :failed + @scanner.pos = s0 + s0 = :failed + else + s2 = parse_piece + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = { 'color' => s1, 'kind' => s2 } + end end - parse_comments - @reported_pos = s0 - s0 = s2.unshift(s1) + if s0 == :failed + s0 = @scanner.pos + if match_str(' * ') != :failed + @reported_pos = s0 + s1 = {} + end + s0 = s1 + end + s0 end - s0 - end - # firstboard : comment* - def parse_firstboard - s0 = @current_pos - s1 = parse_comments - @reported_pos = s0 - s1.empty? ? {} : { "comments" => s1 } - end - - # move : (normalmove | specialmove) time? comment* - def parse_move - s0 = @current_pos - s1 = parse_normal_move - s1 = parse_special_move if s1 == :failed - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = parse_time - s2 = nil if s2 == :failed - s3 = parse_comments + # komabetsu : komabetsuline* + def parse_komabetsu + s0 = @scanner.pos + s1 = [] + s2 = parse_komabetsu_line + while s2 != :failed + s1 << s2 + s2 = parse_komabetsu_line + end @reported_pos = s0 - s0 = -> (move, time, comments) do - ret = {} - ret["comments"] = comments if !comments.empty? - ret["time"] = time if time - if move["special"] - ret["special"] = move["special"] - else - ret["move"] = move - end - ret - end.call(s1, s2, s3) + transform_komabetsu_lines(s1) end - s0 - end - # normalmove : teban xy xy piece nl - def parse_normal_move - s0 = @current_pos - s1 = parse_teban - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = parse_xy - if s2 == :failed - @current_pos = s0 + # komabetsuline : "P" teban xypiece+ nl + def parse_komabetsu_line + s0 = @scanner.pos + if match_str('P') == :failed + @scanner.pos = s0 s0 = :failed else - s3 = parse_xy - if s3 == :failed - @current_pos = s0 + s2 = parse_teban + if s2 == :failed + @scanner.pos = s0 s0 = :failed else - s4 = parse_piece + s4 = parse_xy_piece if s4 == :failed - @current_pos = s0 + s3 = :failed + else + s3 = [] + while s4 != :failed + s3 << s4 + s4 = parse_xy_piece + end + end + if s3 == :failed + @scanner.pos = s0 s0 = :failed elsif parse_nl != :failed @reported_pos = s0 - s0 = -> (color, from, to, piece) do - ret = { "color" => color, "to" => to, "piece" => piece } - ret["from"] = from if from["x"] != 0 - ret - end.call(s1, s2, s3, s4) + s0 = { 'teban' => s2, 'pieces' => s3 } else - @current_pos = s0 + @scanner.pos = s0 s0 = :failed end end end + s0 end - s0 - end - # specialmove : "%" [-+_A-Z]+ nl - def parse_special_move - s0 = @current_pos - s1 = match_str("%") - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s3 = match_regexp(/^[\-+_A-Z]/) - if s3 == :failed - s2 = :failed + # moves : firstboard move* comment* + def parse_moves + s0 = @scanner.pos + s1 = parse_firstboard + if s1 == :failed + @scanner.pos = s0 + s0 = :failed else s2 = [] + s3 = parse_move while s3 != :failed s2 << s3 - s3 = match_regexp(/^[\-+_A-Z]/) + s3 = parse_move end + parse_comments + @reported_pos = s0 + s0 = s2.unshift(s1) end - if s2 == :failed - @current_pos = s0 + s0 + end + + # firstboard : comment* + def parse_firstboard + s0 = @scanner.pos + s1 = parse_comments + @reported_pos = s0 + s1.empty? ? {} : { 'comments' => s1 } + end + + # move : (normalmove | specialmove) time? comment* + def parse_move + s0 = @scanner.pos + s1 = parse_normal_move + s1 = parse_special_move if s1 == :failed + if s1 == :failed + @scanner.pos = s0 s0 = :failed - elsif parse_nl != :failed - @reported_pos = s0 - s0 = { "special" => s2.join } else - @current_pos = s0 + s2 = parse_time + s2 = nil if s2 == :failed + s3 = parse_comments + @reported_pos = s0 + s0 = -> (move, time, comments) do + ret = {} + ret['comments'] = comments unless comments.empty? + ret['time'] = time if time + if move['special'] + ret['special'] = move['special'] + else + ret['move'] = move + end + ret + end.call(s1, s2, s3) + end + s0 + end + + # normalmove : teban xy xy piece nl + def parse_normal_move + s0 = @scanner.pos + s1 = parse_teban + if s1 == :failed + @scanner.pos = s0 s0 = :failed + else + s2 = parse_xy + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + s3 = parse_xy + if s3 == :failed + @scanner.pos = s0 + s0 = :failed + else + s4 = parse_piece + if s4 == :failed + @scanner.pos = s0 + s0 = :failed + elsif parse_nl != :failed + @reported_pos = s0 + s0 = -> (color, from, to, piece) do + ret = { 'color' => color, 'to' => to, 'piece' => piece } + ret['from'] = from if from['x'] != 0 + ret + end.call(s1, s2, s3, s4) + else + @scanner.pos = s0 + s0 = :failed + end + end + end end + s0 end - s0 - end - # teban : "+" | "-" - def parse_teban - s0 = @current_pos - s1 = match_str("+") - if s1 != :failed - @reported_pos = s0 - s1 = 0 + # specialmove : "%" [-+_A-Z]+ nl + def parse_special_move + s0 = @scanner.pos + s1 = match_str('%') + if s1 == :failed + @scanner.pos = s0 + s0 = :failed + else + s3 = match_regexp(/[-+_A-Z]/) + if s3 == :failed + s2 = :failed + else + s2 = [] + while s3 != :failed + s2 << s3 + s3 = match_regexp(/[-+_A-Z]/) + end + end + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + elsif parse_nl != :failed + @reported_pos = s0 + s0 = { 'special' => s2.join } + else + @scanner.pos = s0 + s0 = :failed + end + end + s0 end - s0 = s1 - if s0 == :failed - s0 = @current_pos - s1 = match_str("-") + + # teban : "+" | "-" + def parse_teban + s0 = @scanner.pos + s1 = match_str('+') if s1 != :failed @reported_pos = s0 - s1 = 1 + s1 = 0 end s0 = s1 + if s0 == :failed + s0 = @scanner.pos + s1 = match_str('-') + if s1 != :failed + @reported_pos = s0 + s1 = 1 + end + s0 = s1 + end + s0 end - s0 - end - # comment : "'" nonls nl - def parse_comment - s0 = @current_pos - if match_str("'") == :failed - @current_pos = s0 - :failed - else - s2 = parse_nonls - if parse_nl == :failed - @current_pos = s0 + # comment : "'" nonls nl + def parse_comment + s0 = @scanner.pos + if match_str("'") == :failed + @scanner.pos = s0 :failed else - @reported_pos = s0 - s2.join + s2 = parse_nonls + if parse_nl == :failed + @scanner.pos = s0 + :failed + else + @reported_pos = s0 + s2.join + end end end - end - # comments : comment* - def parse_comments - stack = [] - matched = parse_comment - while matched != :failed - stack << matched + # comments : comment* + def parse_comments + stack = [] matched = parse_comment + while matched != :failed + stack << matched + matched = parse_comment + end + stack end - stack - end - # time : "T" [0-9]* nl - def parse_time - s0 = @current_pos - if match_str("T") == :failed - @current_pos = s0 - s0 = :failed - else - s2 = match_digits - if parse_nl == :failed - @current_pos = s0 + # time : "T" [0-9]* nl + def parse_time + s0 = @scanner.pos + if match_str('T') == :failed + @scanner.pos = s0 s0 = :failed else - @reported_pos = s0 - s0 = { "now" => sec2time(s2.join.to_i) } + s2 = match_digits + if parse_nl == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = { 'now' => sec2time(s2.join.to_i) } + end end + s0 end - s0 - end - # xy : [0-9] [0-9] - def parse_xy - s0 = @current_pos - s1 = match_digit - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = match_digit - if s2 == :failed - @current_pos = s0 + # xy : [0-9] [0-9] + def parse_xy + s0 = @scanner.pos + s1 = match_digit + if s1 == :failed + @scanner.pos = s0 s0 = :failed else - @reported_pos = s0 - s0 = { "x" => s1.to_i, "y" => s2.to_i } + s2 = match_digit + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = { 'x' => s1.to_i, 'y' => s2.to_i } + end end + s0 end - s0 - end - # piece : [A-Z] [A-Z] - def parse_piece - s0 = @current_pos - s1 = match_regexp(/^[A-Z]/) - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = match_regexp(/^[A-Z]/) - if s2 == :failed - @current_pos = s0 + # piece : [A-Z] [A-Z] + def parse_piece + s0 = @scanner.pos + s1 = match_regexp(/[A-Z]/) + if s1 == :failed + @scanner.pos = s0 s0 = :failed else - @reported_pos = s0 - s0 = s1 + s2 + s2 = match_regexp(/[A-Z]/) + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = s1 + s2 + end end + s0 end - s0 - end - # xypiece : xy piece - def parse_xy_piece - s0 = @current_pos - s1 = parse_xy - if s1 == :failed - @current_pos = s0 - s0 = :failed - else - s2 = parse_piece - if s2 == :failed - @current_pos = s0 + # xypiece : xy piece + def parse_xy_piece + s0 = @scanner.pos + s1 = parse_xy + if s1 == :failed + @scanner.pos = s0 s0 = :failed else - @reported_pos = s0 - s0 = { "xy" => s1, "piece" => s2 } + s2 = parse_piece + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + @reported_pos = s0 + s0 = { 'xy' => s1, 'piece' => s2 } + end end + s0 end - s0 - end - # nl : ("\r"? "\n") | " "* "," - def parse_nl - s0 = @current_pos - s1 = match_str("\r") - s1 = nil if s1 == :failed - s2 = match_str("\n") - if s2 == :failed - @current_pos = s0 - s0 = :failed - else - s0 = [s1, s2] - end - if s0 == :failed - s0 = @current_pos - s1 = match_spaces - s2 = match_str(",") + # nl : ("\r"? "\n") | " "* "," + def parse_nl + s0 = @scanner.pos + s1 = match_str("\r") + s1 = nil if s1 == :failed + s2 = match_str("\n") if s2 == :failed - @current_pos = s0 + @scanner.pos = s0 s0 = :failed else s0 = [s1, s2] end + if s0 == :failed + s0 = @scanner.pos + s1 = match_spaces + s2 = match_str(',') + if s2 == :failed + @scanner.pos = s0 + s0 = :failed + else + s0 = [s1, s2] + end + end + s0 end - s0 - end - # nonl : [^\r\n] - def parse_nonl - match_regexp(/^[^\r\n]/) - end + # nonl : [^\r\n] + def parse_nonl + match_regexp(/[^\r\n]/) + end - # nonls : nonl* - def parse_nonls - stack = [] - matched = parse_nonl - while matched != :failed - stack << matched + # nonls : nonl* + def parse_nonls + stack = [] matched = parse_nonl + while matched != :failed + stack << matched + matched = parse_nonl + end + stack end - stack - end - # lines to jkf - def transform_komabetsu_lines(lines) - board = generate_empty_board - hands = [ - { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 }, - { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 } - ] - all = { "FU" => 18, "KY" => 4, "KE" => 4, "GI" => 4, "KI" => 4, "KA" => 2, "HI" => 2 } + # lines to jkf + def transform_komabetsu_lines(lines) + board = generate_empty_board + hands = [ + { 'FU' => 0, 'KY' => 0, 'KE' => 0, 'GI' => 0, 'KI' => 0, 'KA' => 0, 'HI' => 0 }, + { 'FU' => 0, 'KY' => 0, 'KE' => 0, 'GI' => 0, 'KI' => 0, 'KA' => 0, 'HI' => 0 } + ] + all = { 'FU' => 18, 'KY' => 4, 'KE' => 4, 'GI' => 4, 'KI' => 4, 'KA' => 2, 'HI' => 2 } - lines.each do |line| - line["pieces"].each do |piece| - xy = piece["xy"] - if xy["x"] == 0 - if piece["piece"] == "AL" - hands[line["teban"]] = all - return { "preset" => "OTHER", "data" => { "board" => board, "hands" => hands } } + lines.each do |line| + line['pieces'].each do |piece| + xy = piece['xy'] + if xy['x'] == 0 + if piece['piece'] == 'AL' + hands[line['teban']] = all + return { 'preset' => 'OTHER', 'data' => { 'board' => board, 'hands' => hands } } + end + obj = hands[line['teban']] + obj[piece['piece']] += 1 + else + board[xy['x'] - 1][xy['y'] - 1] = { 'color' => line['teban'], + 'kind' => piece['piece'] } end - obj = hands[line["teban"]] - obj[piece["piece"]] += 1 - else - board[xy["x"] - 1][xy["y"] - 1] = { "color" => line["teban"], - "kind" => piece["piece"] } + all[piece['piece']] -= 1 if piece['piece'] != 'OU' end - all[piece["piece"]] -= 1 if piece["piece"] != "OU" end + + { 'preset' => 'OTHER', 'data' => { 'board' => board, 'hands' => hands } } end - { "preset" => "OTHER", "data" => { "board" => board, "hands" => hands } } - end - - # return empty board jkf - def generate_empty_board - board = [] - 9.times do |_i| - line = [] - 9.times do |_j| - line << {} + # return empty board jkf + def generate_empty_board + board = [] + 9.times do |_i| + line = [] + 9.times do |_j| + line << {} + end + board << line end - board << line + board end - board - end - # sec to time(m, s) - def sec2time(sec) - s = sec % 60 - m = (sec - s) / 60 - { "m" => m, "s" => s } - end + # sec to time(m, s) + def sec2time(sec) + s = sec % 60 + m = (sec - s) / 60 + { 'm' => m, 's' => s } + end - # return hirate board jkf - def get_hirate - [ - [{ "color" => 1, "kind" => "KY" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "KY" }], - [{ "color" => 1, "kind" => "KE" }, { "color" => 1, "kind" => "KA" }, - { "color" => 1, "kind" => "FU" }, {}, {}, {}, { "color" => 0, "kind" => "FU" }, - { "color" => 0, "kind" => "HI" }, { "color" => 0, "kind" => "KE" }], - [{ "color" => 1, "kind" => "GI" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "GI" }], - [{ "color" => 1, "kind" => "KI" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "KI" }], - [{ "color" => 1, "kind" => "OU" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "OU" }], - [{ "color" => 1, "kind" => "KI" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "KI" }], - [{ "color" => 1, "kind" => "GI" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "GI" }], - [{ "color" => 1, "kind" => "KE" }, { "color" => 1, "kind" => "HI" }, - { "color" => 1, "kind" => "FU" }, {}, {}, {}, { "color" => 0, "kind" => "FU" }, - { "color" => 0, "kind" => "KA" }, { "color" => 0, "kind" => "KE" }], - [{ "color" => 1, "kind" => "KY" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {}, - { "color" => 0, "kind" => "FU" }, {}, { "color" => 0, "kind" => "KY" }] - ] - end + # return hirate board jkf + def hirate + [ + [{ 'color' => 1, 'kind' => 'KY' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'KY' }], + [{ 'color' => 1, 'kind' => 'KE' }, { 'color' => 1, 'kind' => 'KA' }, + { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, { 'color' => 0, 'kind' => 'FU' }, + { 'color' => 0, 'kind' => 'HI' }, { 'color' => 0, 'kind' => 'KE' }], + [{ 'color' => 1, 'kind' => 'GI' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'GI' }], + [{ 'color' => 1, 'kind' => 'KI' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'KI' }], + [{ 'color' => 1, 'kind' => 'OU' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'OU' }], + [{ 'color' => 1, 'kind' => 'KI' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'KI' }], + [{ 'color' => 1, 'kind' => 'GI' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'GI' }], + [{ 'color' => 1, 'kind' => 'KE' }, { 'color' => 1, 'kind' => 'HI' }, + { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, { 'color' => 0, 'kind' => 'FU' }, + { 'color' => 0, 'kind' => 'KA' }, { 'color' => 0, 'kind' => 'KE' }], + [{ 'color' => 1, 'kind' => 'KY' }, {}, { 'color' => 1, 'kind' => 'FU' }, {}, {}, {}, + { 'color' => 0, 'kind' => 'FU' }, {}, { 'color' => 0, 'kind' => 'KY' }] + ] + end - # normalize header key - def normalize_header_key(key) - { - "EVENT" => "棋戦", - "SITE" => "場所", - "START_TIME" => "開始日時", - "END_TIME" => "終了日時", - "TIME_LIMIT" => "持ち時間" - }[key] || key + # normalize header key + def normalize_header_key(key) + { + 'EVENT' => '棋戦', + 'SITE' => '場所', + 'START_TIME' => '開始日時', + 'END_TIME' => '終了日時', + 'TIME_LIMIT' => '持ち時間' + }[key] || key + end end end end