module Jkf::Converter class Kif def convert(jkf) hash = if jkf.is_a?(Hash) jkf else JSON.parse(jkf) end @forks = [] result = '' result += convert_header(hash['header']) if hash['header'] result += convert_initial(hash['initial']) if hash['initial'] result += "手数----指手---------消費時間--\n" result += convert_moves(hash['moves']) if @forks.size > 0 result += "\n" result += @forks.join("\n") end result end protected def convert_header(header) header.map { |(key, value)| "#{key}:#{value}\n" }.join end def convert_initial(initial) result = '' result += "手合割:#{preset2str(initial["preset"])}\n" if initial["preset"] != "OTHER" data = initial["data"] if data if data['color'] == 0 result += "先手番\n" elsif data['color'] == 1 result += "後手番\n" end if data['hands'] if data['hands'][0] result += '先手の持駒:' result += convert_motigoma(data['hands'][0]) end if data['hands'][1] result += '後手の持駒:' result += convert_motigoma(data['hands'][1]) end end if data['board'] result += " 9 8 7 6 5 4 3 2 1\n" result += "+---------------------------+\n" 9.times { |y| line = "|" 9.times { |x| line += convert_board_piece(data['board'][8-x][y]) } line += "|#{n2kan(y+1)}\n" result += line } result += "+---------------------------+\n" end end result end def convert_moves(moves, idx=0) result = '' moves.each_with_index { |move, i| if move['special'] result_move = "%4d "%(i+idx) result_move += ljust(special2kan(move['special']), 13) result_move += convert_time(move['time']) if move['time'] result_move += "+" if move['forks'] result_move += "\n" result += result_move # first_board+speical分を引く(-2) result += convert_special(move['special'], i-2+idx) if move['special'] else if move['move'] result_move = "%4d "%(i+idx) result_move += convert_move(move['move']) result_move += convert_time(move['time']) if move['time'] result_move += "+" if move['forks'] result_move += "\n" result += result_move end if move['comments'] result += convert_comments(move['comments']) end @forks.unshift convert_forks(move['forks'], i+idx) if move['forks'] end } result end def convert_move(move) result = if move['to'] n2zen(move['to']['x']) + n2kan(move['to']['y']) elsif move['same'] '同 ' else raise "error??" end result += csa2kind(move['piece']) result += '成' if move['promote'] result += if move['from'] "(#{move['from']['x']}#{move['from']['y']})" else '打' end result = ljust(result,13) result end def convert_time(time) "(%2d:%02d/%02d:%02d:%02d)"%[ time['now']['m'], time['now']['s'], time['total']['h'], time['total']['m'], time['total']['s'], ] end def convert_special(special, index) result = "まで#{index+1}手" if special == 'TORYO' || special =~ /ILLEGAL/ turn = index % 2 == 0 ? '後' : '先' result += "で#{turn}手の" result += case special when "TORYO" then "勝ち" when "ILLEGAL_ACTION" then "反則勝ち" when "ILLEGAL_MOVE" then "反則負け" end else turn = index % 2 == 0 ? '先' : '後' result += case special when "TIME_UP" then "で時間切れにより#{turn}手の勝ち" when "CHUDAN" then "で中断" when "JISHOGI" then "で持将棋" when "SENNICHITE" then "で千日手" when "TSUMI" then "で詰み" when "FUZUMI" then "で不詰" end end result += "\n" result end def convert_comments(comments) comments.map { |comment| "*#{comment}\n" }.join end def convert_forks(forks, index) result = "\n" result = "変化:%4d手\n"%[index] forks.each do |moves| result += convert_moves(moves, index) end result end def convert_board_piece(piece) result = '' if piece == {} result = ' ・' else result += piece['color'] == 0 ? ' ' : 'v' result += csa2kind(piece['kind']) end result end def convert_motigoma(pieces) pieces.to_a.reverse.map do |piece, num| if num > 0 str = csa2kind(piece) if num > 1 str += n2kan(num/10) if num / 10 > 0 num %= 10 str += n2kan(num) end str else nil end end.compact.join(' ') + " \n" end protected def n2zen(n) "0123456789"[n] end def n2kan(n) "〇一二三四五六七八九"[n] end def csa2kind(csa) { "FU" => "歩", "KY" => "香", "KE" => "桂", "GI" => "銀", "KI" => "金", "KA" => "角", "HI" => "飛", "OU" => "玉", "TO" => "と", "NY" => "成香", "NK" => "成桂", "NG" => "成銀", "UM" => "馬", "RY" => "龍", }[csa] end def preset2str(preset) { "HIRATE" => "平手", "KY" => "香落ち", "KY_R" => "右香落ち", "KA" => "角落ち", "HI" => "飛車落ち", "HIKY" => "飛香落ち", "2" => "二枚落ち", "3" => "三枚落ち", "4" => "四枚落ち", "5" => "五枚落ち", "5_L" => "左五枚落ち", "6" => "六枚落ち", "8" => "八枚落ち", "10" => "十枚落ち", "OTHER" => "その他" }[preset] end def special2kan(special) case special when "CHUDAN" then "中断" when "TORYO" then "投了" when "JISHOGI" then "持将棋" when "SENNICHITE" then "千日手" when "TSUMI" then "詰み" when "FUZUMI" then "不詰" when "TIME_UP" then "切れ負け" when "ILLEGAL_ACTION" then "反則勝ち" when "ILLEGAL_MOVE" then "反則負け" end end def ljust(str, n) len = 0 str.each_codepoint { |codepoint| len += codepoint > 255 ? 2 : 1 } str + ' '*(n-len) end end end