jkf 0.4.3 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +16 -0
- data/.rubocop.yml +46 -990
- data/.rubocop_todo.yml +1 -5
- data/CHANGELOG.md +63 -0
- data/Gemfile +11 -9
- data/Guardfile +3 -3
- data/README.en.md +28 -15
- data/README.md +9 -5
- data/Rakefile +7 -2
- data/bench.rb +12 -0
- data/bin/console +4 -4
- data/jkf.gemspec +14 -12
- data/lib/jkf/converter/base.rb +12 -10
- data/lib/jkf/converter/csa.rb +141 -150
- data/lib/jkf/converter/ki2.rb +93 -91
- data/lib/jkf/converter/kif.rb +105 -99
- data/lib/jkf/converter/kifuable.rb +160 -160
- data/lib/jkf/converter.rb +6 -8
- data/lib/jkf/parser/base.rb +81 -95
- data/lib/jkf/parser/csa.rb +652 -667
- data/lib/jkf/parser/ki2.rb +332 -338
- data/lib/jkf/parser/kif.rb +468 -485
- data/lib/jkf/parser/kifuable.rb +500 -518
- data/lib/jkf/parser.rb +5 -7
- data/lib/jkf/version.rb +1 -2
- data/lib/jkf.rb +6 -6
- data/manifest.scm +143 -0
- data/po/all.pot +176 -0
- data/po/en.po +199 -0
- data/po4a.cfg +11 -0
- metadata +13 -7
- data/.codeclimate.yml +0 -28
- data/.travis.yml +0 -9
data/lib/jkf/converter/csa.rb
CHANGED
@@ -1,174 +1,165 @@
|
|
1
|
-
module Jkf
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def convert_information(header)
|
17
|
-
result = ""
|
18
|
-
if header["先手"] || header["下手"]
|
19
|
-
result += "N+" + (header.delete("先手") || header.delete("下手") || "") + "\n"
|
20
|
-
end
|
21
|
-
if header["後手"] || header["上手"]
|
22
|
-
result += "N-" + (header.delete("後手") || header.delete("上手") || "") + "\n"
|
1
|
+
module Jkf
|
2
|
+
module Converter
|
3
|
+
# CSA v2.2 Converter
|
4
|
+
class Csa < Base
|
5
|
+
VERSION = '2.2'.freeze
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def convert_root(jkf)
|
10
|
+
result = version
|
11
|
+
result += convert_information(jkf['header']) if jkf['header']
|
12
|
+
result += convert_initial(jkf['initial']) if jkf['initial']
|
13
|
+
result += convert_moves(jkf['moves']) if jkf['moves']
|
14
|
+
result
|
23
15
|
end
|
24
|
-
header.each { |(k, v)| result += "$#{csa_header_key(k)}:#{v}\n" }
|
25
|
-
result
|
26
|
-
end
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
result += convert_hands(data["hands"], 0)
|
39
|
-
result += convert_hands(data["hands"], 1)
|
17
|
+
def convert_information(header)
|
18
|
+
result = ''
|
19
|
+
if header['先手'] || header['下手']
|
20
|
+
result += 'N+' + (header.delete('先手') || header.delete('下手') || '') + "\n"
|
21
|
+
end
|
22
|
+
if header['後手'] || header['上手']
|
23
|
+
result += 'N-' + (header.delete('後手') || header.delete('上手') || '') + "\n"
|
24
|
+
end
|
25
|
+
header.each { |(k, v)| result += "$#{csa_header_key(k)}:#{v}\n" }
|
26
|
+
result
|
40
27
|
end
|
41
|
-
result += csa_color(data["color"]) + "\n" if data["color"]
|
42
|
-
result
|
43
|
-
end
|
44
28
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
29
|
+
def convert_initial(initial)
|
30
|
+
result = ''
|
31
|
+
data = initial['data'] || {}
|
32
|
+
result += if initial['preset'] == 'OTHER'
|
33
|
+
convert_board(data['board'])
|
34
|
+
else
|
35
|
+
convert_preset(initial['preset'])
|
36
|
+
end
|
37
|
+
# 持駒
|
38
|
+
if data['hands']
|
39
|
+
result += convert_hands(data['hands'], 0)
|
40
|
+
result += convert_hands(data['hands'], 1)
|
41
|
+
end
|
42
|
+
result += csa_color(data['color']) + "\n" if data['color']
|
43
|
+
result
|
53
44
|
end
|
54
|
-
result
|
55
|
-
end
|
56
45
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
if move["time"]
|
65
|
-
result += "," + convert_time(move["time"])
|
66
|
-
elsif move["move"] || move["special"]
|
46
|
+
def convert_hands(hands, color)
|
47
|
+
result = ''
|
48
|
+
sum = 0
|
49
|
+
hands[color].each_value { |n| sum += n }
|
50
|
+
if sum > 0
|
51
|
+
result += "P#{csa_color(color)}"
|
52
|
+
hands[color].to_a.reverse_each { |(k, v)| v.times { result += "00#{k}" } }
|
67
53
|
result += "\n"
|
68
54
|
end
|
69
|
-
result
|
70
|
-
before_pos = move["move"]["to"] if move["move"] && move["move"]["to"]
|
55
|
+
result
|
71
56
|
end
|
72
|
-
result
|
73
|
-
end
|
74
57
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
58
|
+
def convert_moves(moves)
|
59
|
+
result = ''
|
60
|
+
before_pos = nil
|
61
|
+
moves.each do |move|
|
62
|
+
next if move == {}
|
63
|
+
result += convert_move(move['move'], before_pos) if move['move']
|
64
|
+
result += convert_special(move['special'], move['color']) if move['special']
|
65
|
+
if move['time']
|
66
|
+
result += ',' + convert_time(move['time'])
|
67
|
+
elsif move['move'] || move['special']
|
68
|
+
result += "\n"
|
69
|
+
end
|
70
|
+
result += convert_comments(move['comments']) if move['comments']
|
71
|
+
before_pos = move['move']['to'] if move['move'] && move['move']['to']
|
72
|
+
end
|
73
|
+
result
|
74
|
+
end
|
85
75
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
76
|
+
def convert_move(move, before_pos)
|
77
|
+
result = csa_color(move['color'])
|
78
|
+
result += move['from'] ? pos2str(move['from']) : '00'
|
79
|
+
result += if move['to']
|
80
|
+
pos2str(move['to']) + move['piece']
|
81
|
+
else
|
82
|
+
pos2str(before_pos) + move['piece']
|
83
|
+
end
|
84
|
+
result
|
85
|
+
end
|
91
86
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
87
|
+
def convert_special(special, color = nil)
|
88
|
+
result = '%'
|
89
|
+
result += csa_color(color) if color
|
90
|
+
result + special
|
91
|
+
end
|
96
92
|
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
def convert_time(time)
|
94
|
+
sec = (time['now']['m'] * 60) + time['now']['s']
|
95
|
+
"T#{sec}\n"
|
96
|
+
end
|
100
97
|
|
101
|
-
|
102
|
-
|
103
|
-
9.times do |y|
|
104
|
-
result += "P#{y + 1}"
|
105
|
-
9.times do |x|
|
106
|
-
piece = board[8 - x][y]
|
107
|
-
result += if piece == {}
|
108
|
-
" * "
|
109
|
-
else
|
110
|
-
csa_color(piece["color"]) + piece["kind"]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
result += "\n"
|
98
|
+
def convert_comments(comments)
|
99
|
+
comments.map { |comment| "'#{comment}" }.join("\n") + "\n"
|
114
100
|
end
|
115
|
-
result
|
116
|
-
end
|
117
101
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
"
|
131
|
-
when "HIKY" # 飛香落ち
|
132
|
-
"22HI11KY91KY"
|
133
|
-
when "2" # 二枚落ち
|
134
|
-
"82HI22KA"
|
135
|
-
when "3" # 三枚落ち
|
136
|
-
"82HI22KA91KY"
|
137
|
-
when "4" # 四枚落ち
|
138
|
-
"82HI22KA11KY91KY"
|
139
|
-
when "5" # 五枚落ち
|
140
|
-
"82HI22KA81KE11KY91KY"
|
141
|
-
when "5_L" # 左五枚落ち
|
142
|
-
"82HI22KA21KE11KY91KY"
|
143
|
-
when "6" # 六枚落ち
|
144
|
-
"82HI22KA21KE81KE11KY91KY"
|
145
|
-
when "8" # 八枚落ち
|
146
|
-
"82HI22KA31GI71GI21KE81KE11KY91KY"
|
147
|
-
when "10" # 十枚落ち
|
148
|
-
"82HI22KA41KI61KI31GI71GI21KE81KE11KY91KY"
|
102
|
+
def convert_board(board)
|
103
|
+
result = ''
|
104
|
+
9.times do |y|
|
105
|
+
result += "P#{y + 1}"
|
106
|
+
9.times do |x|
|
107
|
+
piece = board[8 - x][y]
|
108
|
+
result += if piece == {}
|
109
|
+
' * '
|
110
|
+
else
|
111
|
+
csa_color(piece['color']) + piece['kind']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
result += "\n"
|
149
115
|
end
|
150
|
-
|
116
|
+
result
|
117
|
+
end
|
151
118
|
|
152
|
-
|
153
|
-
|
154
|
-
|
119
|
+
def convert_preset(preset)
|
120
|
+
'PI' + PRESET_NAME_TO_CSA_MAPPING[preset]
|
121
|
+
end
|
155
122
|
|
156
|
-
|
157
|
-
|
158
|
-
|
123
|
+
PRESET_NAME_TO_CSA_MAPPING = {
|
124
|
+
'HIRATE' => '', # 平手
|
125
|
+
'KY' => '11KY', # 香落ち
|
126
|
+
'KY_R' => '91KY', # 右香落ち
|
127
|
+
'KA' => '22KA', # 角落ち
|
128
|
+
'HI' => '82HI', # 飛車落ち
|
129
|
+
'HIKY' => '22HI11KY91KY', # 飛香落ち
|
130
|
+
'2' => '82HI22KA', # 二枚落ち
|
131
|
+
'3' => '82HI22KA91KY', # 三枚落ち
|
132
|
+
'4' => '82HI22KA11KY91KY', # 四枚落ち
|
133
|
+
'5' => '82HI22KA81KE11KY91KY', # 五枚落ち
|
134
|
+
'5_L' => '82HI22KA21KE11KY91KY', # 左五枚落ち
|
135
|
+
'6' => '82HI22KA21KE81KE11KY91KY', # 六枚落ち
|
136
|
+
'8' => '82HI22KA31GI71GI21KE81KE11KY91KY', # 八枚落ち
|
137
|
+
'10' => '82HI22KA41KI61KI31GI71GI21KE81KE11KY91KY' # 十枚落ち
|
138
|
+
}.freeze
|
139
|
+
|
140
|
+
private_constant :PRESET_NAME_TO_CSA_MAPPING
|
141
|
+
|
142
|
+
def csa_color(color)
|
143
|
+
color == 0 ? '+' : '-'
|
144
|
+
end
|
159
145
|
|
160
|
-
|
161
|
-
|
162
|
-
|
146
|
+
def pos2str(pos)
|
147
|
+
'%d%d' % [pos['x'], pos['y']]
|
148
|
+
end
|
149
|
+
|
150
|
+
def version
|
151
|
+
"V#{VERSION}\n"
|
152
|
+
end
|
163
153
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
154
|
+
def csa_header_key(key)
|
155
|
+
{
|
156
|
+
'棋戦' => 'EVENT',
|
157
|
+
'場所' => 'SITE',
|
158
|
+
'開始日時' => 'START_TIME',
|
159
|
+
'終了日時' => 'END_TIME',
|
160
|
+
'持ち時間' => 'TIME_LIMIT'
|
161
|
+
}[key] || key
|
162
|
+
end
|
172
163
|
end
|
173
164
|
end
|
174
165
|
end
|
data/lib/jkf/converter/ki2.rb
CHANGED
@@ -1,113 +1,115 @@
|
|
1
|
-
module Jkf
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Jkf
|
2
|
+
module Converter
|
3
|
+
# KI2 Converter
|
4
|
+
class Ki2 < Base
|
5
|
+
include Kifuable
|
5
6
|
|
6
|
-
|
7
|
+
protected
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def convert_root(jkf)
|
10
|
+
reset!
|
11
|
+
setup_players!(jkf)
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
result = ''
|
14
|
+
result += convert_header(jkf['header']) if jkf['header']
|
15
|
+
result += convert_initial(jkf['initial']) if jkf['initial']
|
16
|
+
result += @header2.join + "\n"
|
17
|
+
result += convert_moves(jkf['moves']) if jkf['moves']
|
18
|
+
unless @forks.empty?
|
19
|
+
result += "\n"
|
20
|
+
result += @forks.join("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
result
|
20
24
|
end
|
21
25
|
|
22
|
-
|
23
|
-
|
26
|
+
def convert_header(header)
|
27
|
+
header.map do |(key, value)|
|
28
|
+
result = add_header(key, value)
|
29
|
+
if key =~ /\A[先後上下]手\Z/
|
30
|
+
nil
|
31
|
+
else
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end.compact.join
|
35
|
+
end
|
24
36
|
|
25
|
-
|
26
|
-
|
27
|
-
result = add_header(key, value)
|
37
|
+
def add_header(key, value)
|
38
|
+
result = "#{key}:#{value}\n"
|
28
39
|
if key =~ /\A[先後上下]手\Z/
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def add_header(key, value)
|
37
|
-
result = "#{key}:#{value}\n"
|
38
|
-
if key =~ /\A[先後上下]手\Z/
|
39
|
-
if key =~ /[先下]/
|
40
|
-
@header2.unshift result
|
41
|
-
else
|
42
|
-
@header2 << result
|
40
|
+
if key =~ /[先下]/
|
41
|
+
@header2.unshift result
|
42
|
+
else
|
43
|
+
@header2 << result
|
44
|
+
end
|
43
45
|
end
|
46
|
+
result
|
44
47
|
end
|
45
|
-
result
|
46
|
-
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
49
|
+
def convert_moves(moves, idx = 0)
|
50
|
+
result = ''
|
51
|
+
j = 0
|
52
|
+
before_split = ''
|
53
|
+
moves.each_with_index do |move, i|
|
54
|
+
if move['special']
|
55
|
+
# first_board+speical分を引く(-2)
|
56
|
+
result += convert_special_and_split(move, i + idx - 2)
|
57
|
+
else
|
58
|
+
result += before_split
|
59
|
+
if move['move']
|
60
|
+
j += 1
|
61
|
+
result_move, before_split = convert_move_and_split(move, j)
|
62
|
+
result += result_move
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
if move['comments']
|
66
|
+
unless result.end_with?("\n") || result.empty?
|
67
|
+
result += "\n"
|
68
|
+
before_split = ''
|
69
|
+
j = 0
|
70
|
+
end
|
71
|
+
result += convert_comments(move['comments'])
|
69
72
|
end
|
70
|
-
result += convert_comments(move["comments"])
|
71
|
-
end
|
72
73
|
|
73
|
-
|
74
|
+
@forks.unshift convert_forks(move['forks'], i + idx) if move['forks']
|
75
|
+
end
|
74
76
|
end
|
77
|
+
result
|
75
78
|
end
|
76
|
-
result
|
77
|
-
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
def convert_special_and_split(hash, index)
|
81
|
+
"\n" + convert_special(hash['special'], index)
|
82
|
+
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
84
|
+
def convert_move_and_split(move, num)
|
85
|
+
result = convert_move(move['move'])
|
86
|
+
split = if num % 6 == 0
|
87
|
+
"\n"
|
88
|
+
else
|
89
|
+
result.size == 4 ? ' ' * 4 : ' ' * 2
|
90
|
+
end
|
91
|
+
[result, split]
|
92
|
+
end
|
92
93
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
94
|
+
def convert_move(move)
|
95
|
+
result = move['color'] == 0 ? '▲' : '△'
|
96
|
+
result += convert_piece_with_pos(move)
|
97
|
+
result += csa2relative(move['relative']) if move['relative']
|
98
|
+
result
|
99
|
+
end
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
101
|
+
def csa2relative(relative)
|
102
|
+
case relative
|
103
|
+
when 'L' then '左'
|
104
|
+
when 'C' then '直'
|
105
|
+
when 'R' then '右'
|
106
|
+
when 'U' then '上'
|
107
|
+
when 'M' then '寄'
|
108
|
+
when 'D' then '引'
|
109
|
+
when 'H' then '打'
|
110
|
+
else
|
111
|
+
''
|
112
|
+
end
|
111
113
|
end
|
112
114
|
end
|
113
115
|
end
|