jkf 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +28 -0
- data/.hound.yml +3 -0
- data/.rubocop.yml +1009 -0
- data/.rubocop_todo.yml +11 -0
- data/.travis.yml +3 -0
- data/Gemfile +17 -2
- data/Guardfile +19 -62
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/jkf.gemspec +13 -18
- data/lib/jkf.rb +3 -3
- data/lib/jkf/converter.rb +6 -4
- data/lib/jkf/converter/base.rb +8 -0
- data/lib/jkf/converter/csa.rb +109 -104
- data/lib/jkf/converter/ki2.rb +63 -223
- data/lib/jkf/converter/kif.rb +62 -239
- data/lib/jkf/converter/kifuable.rb +189 -0
- data/lib/jkf/parser.rb +5 -4
- data/lib/jkf/parser/base.rb +53 -10
- data/lib/jkf/parser/csa.rb +279 -474
- data/lib/jkf/parser/ki2.rb +131 -965
- data/lib/jkf/parser/kif.rb +191 -1142
- data/lib/jkf/parser/kifuable.rb +608 -0
- data/lib/jkf/version.rb +1 -1
- metadata +10 -59
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2016-02-24 04:22:16 +0900 using RuboCop version 0.37.2.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 30
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 127
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in jkf.gemspec
|
4
3
|
gemspec
|
4
|
+
|
5
|
+
gem "rake", "~> 10.0"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "yard", require: false
|
9
|
+
gem "redcarpet", require: false
|
10
|
+
|
11
|
+
gem "rubocop", "~> 0.37.2", require: false
|
12
|
+
gem "guard-rubocop", require: false
|
13
|
+
end
|
14
|
+
|
15
|
+
group :test do
|
16
|
+
gem "codeclimate-test-reporter", require: nil
|
17
|
+
gem "rspec", "~> 3.0", require: false
|
18
|
+
gem "guard-rspec", require: false
|
19
|
+
end
|
data/Guardfile
CHANGED
@@ -1,70 +1,27 @@
|
|
1
|
-
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
1
|
+
scope(groups: %w(specs))
|
3
2
|
|
4
|
-
|
5
|
-
# directories %w(app lib config test spec features) \
|
6
|
-
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
3
|
+
directories %w(spec lib)
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# $ mkdir config
|
13
|
-
# $ mv Guardfile config/
|
14
|
-
# $ ln -s config/Guardfile .
|
15
|
-
#
|
16
|
-
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
5
|
+
group :specs, halt_on_fail: true do
|
6
|
+
guard :rspec, cmd: "bundle exec rspec", failed_mode: :keep do
|
7
|
+
require "guard/rspec/dsl"
|
8
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
17
9
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# installed the spring binstubs per the docs)
|
24
|
-
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
-
# * 'just' rspec: 'rspec'
|
10
|
+
# RSpec files
|
11
|
+
rspec = dsl.rspec
|
12
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
13
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
14
|
+
watch(rspec.spec_files)
|
26
15
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# Feel free to open issues for suggestions and improvements
|
32
|
-
|
33
|
-
# RSpec files
|
34
|
-
rspec = dsl.rspec
|
35
|
-
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
-
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
-
watch(rspec.spec_files)
|
38
|
-
|
39
|
-
# Ruby files
|
40
|
-
ruby = dsl.ruby
|
41
|
-
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
-
|
43
|
-
# Rails files
|
44
|
-
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
45
|
-
dsl.watch_spec_files_for(rails.app_files)
|
46
|
-
dsl.watch_spec_files_for(rails.views)
|
47
|
-
|
48
|
-
watch(rails.controllers) do |m|
|
49
|
-
[
|
50
|
-
rspec.spec.("routing/#{m[1]}_routing"),
|
51
|
-
rspec.spec.("controllers/#{m[1]}_controller"),
|
52
|
-
rspec.spec.("acceptance/#{m[1]}")
|
53
|
-
]
|
16
|
+
# Ruby files
|
17
|
+
ruby = dsl.ruby
|
18
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
54
19
|
end
|
55
20
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
60
|
-
|
61
|
-
# Capybara features specs
|
62
|
-
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
63
|
-
watch(rails.layouts) { |m| rspec.spec.("features/#{m[1]}") }
|
64
|
-
|
65
|
-
# Turnip features and steps
|
66
|
-
watch(%r{^spec/acceptance/(.+)\.feature$})
|
67
|
-
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
68
|
-
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
21
|
+
guard :rubocop, all_on_start: false, cli: "--rails" do
|
22
|
+
watch(%r{.+\.rb$}) { |m| m[0] }
|
23
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
69
24
|
end
|
70
25
|
end
|
26
|
+
|
27
|
+
# vim: ft=ruby
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Jkf
|
2
|
-
[![Build Status](https://travis-ci.org/iyuuya/jkf.svg?branch=master)](https://travis-ci.org/iyuuya/jkf)
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/jkf.svg)](https://badge.fury.io/rb/jkf) [![Build Status](https://travis-ci.org/iyuuya/jkf.svg?branch=master)](https://travis-ci.org/iyuuya/jkf) [![Code Climate](https://codeclimate.com/github/iyuuya/jkf/badges/gpa.svg)](https://codeclimate.com/github/iyuuya/jkf) [![Test Coverage](https://codeclimate.com/github/iyuuya/jkf/badges/coverage.svg)](https://codeclimate.com/github/iyuuya/jkf/coverage) [![Inline docs](http://inch-ci.org/github/iyuuya/jkf.svg?branch=develop)](http://inch-ci.org/github/iyuuya/jkf)
|
3
3
|
|
4
4
|
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/jkf`. To experiment with that code, run `bin/console` for an interactive prompt.
|
5
5
|
|
data/Rakefile
CHANGED
data/jkf.gemspec
CHANGED
@@ -1,26 +1,21 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "jkf/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
7
|
+
spec.name = "jkf"
|
8
|
+
spec.version = Jkf::VERSION
|
9
|
+
spec.authors = ["iyuuya"]
|
10
|
+
spec.email = ["i.yuuya@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary
|
13
|
-
spec.description
|
14
|
-
spec.homepage
|
15
|
-
spec.license
|
12
|
+
spec.summary = "jkf/csa/kif/ki2 parser and converter"
|
13
|
+
spec.description = "converter/parser of records of shogi"
|
14
|
+
spec.homepage = "https://github.com/iyuuya/jkf"
|
15
|
+
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files
|
18
|
-
spec.bindir
|
19
|
-
spec.executables
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", "~> 1.11"
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
-
spec.add_development_dependency "guard-rspec"
|
26
21
|
end
|
data/lib/jkf.rb
CHANGED
@@ -7,7 +7,7 @@ module Jkf
|
|
7
7
|
class FileTypeError < StandardError; end
|
8
8
|
|
9
9
|
class << self
|
10
|
-
def parse_file(filename, encoding:
|
10
|
+
def parse_file(filename, encoding: "Shift_JIS")
|
11
11
|
parser = case ::File.extname(filename)
|
12
12
|
when /kif/
|
13
13
|
::Jkf::Parser::Kif.new
|
@@ -15,8 +15,8 @@ module Jkf
|
|
15
15
|
::Jkf::Parser::Ki2.new
|
16
16
|
when /csa/
|
17
17
|
::Jkf::Parser::Csa.new
|
18
|
-
|
19
|
-
|
18
|
+
when /jkf|json/
|
19
|
+
JSON
|
20
20
|
end
|
21
21
|
str = File.read(File.expand_path(filename), encoding: encoding).toutf8
|
22
22
|
parser.parse(str)
|
data/lib/jkf/converter.rb
CHANGED
@@ -4,7 +4,9 @@ module Jkf
|
|
4
4
|
end
|
5
5
|
end
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
7
|
+
require "json"
|
8
|
+
require "jkf/converter/base"
|
9
|
+
require "jkf/converter/kifuable"
|
10
|
+
require "jkf/converter/kif"
|
11
|
+
require "jkf/converter/ki2"
|
12
|
+
require "jkf/converter/csa"
|
data/lib/jkf/converter/csa.rb
CHANGED
@@ -1,135 +1,88 @@
|
|
1
1
|
module Jkf::Converter
|
2
|
-
class Csa
|
3
|
-
VERSION =
|
4
|
-
|
5
|
-
def convert(jkf)
|
6
|
-
hash = if jkf.is_a?(Hash)
|
7
|
-
jkf
|
8
|
-
else
|
9
|
-
JSON.parse(jkf)
|
10
|
-
end
|
2
|
+
class Csa < Base
|
3
|
+
VERSION = "2.2".freeze
|
11
4
|
|
5
|
+
def convert_root(jkf)
|
12
6
|
result = version
|
13
|
-
result += convert_information(
|
14
|
-
result += convert_initial(
|
15
|
-
result += convert_moves(
|
7
|
+
result += convert_information(jkf["header"]) if jkf["header"]
|
8
|
+
result += convert_initial(jkf["initial"]) if jkf["initial"]
|
9
|
+
result += convert_moves(jkf["moves"]) if jkf["moves"]
|
16
10
|
result
|
17
11
|
end
|
18
12
|
|
13
|
+
protected
|
14
|
+
|
19
15
|
def convert_information(header)
|
20
|
-
result =
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
result = ""
|
17
|
+
if header["先手"] || header["下手"]
|
18
|
+
result += "N+" + (header.delete("先手") || header.delete("下手") || "") + "\n"
|
19
|
+
end
|
20
|
+
if header["後手"] || header["上手"]
|
21
|
+
result += "N-" + (header.delete("後手") || header.delete("上手") || "") + "\n"
|
22
|
+
end
|
23
|
+
header.each { |(k, v)| result += "$#{csa_header_key(k)}:#{v}\n" }
|
24
24
|
result
|
25
25
|
end
|
26
26
|
|
27
27
|
def convert_initial(initial)
|
28
|
-
result =
|
29
|
-
data = initial[
|
30
|
-
if initial[
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
line += if piece == {}
|
36
|
-
" * "
|
37
|
-
else
|
38
|
-
csa_color(piece['color']) + piece['kind']
|
39
|
-
end
|
40
|
-
}
|
41
|
-
result += line + "\n"
|
42
|
-
}
|
43
|
-
else
|
44
|
-
result += 'PI'
|
45
|
-
case initial['preset']
|
46
|
-
when 'HIRATE'
|
47
|
-
when 'KY' # 香落ち
|
48
|
-
result += '11KY'
|
49
|
-
when 'KY_R' # 右香落ち
|
50
|
-
result += '91KY'
|
51
|
-
when 'KA' # 角落ち
|
52
|
-
result += '22KA'
|
53
|
-
when 'HI' # 飛車落ち
|
54
|
-
result += '82HI'
|
55
|
-
when 'HIKY' # 飛香落ち
|
56
|
-
result += '22HI11KY91KY'
|
57
|
-
when '2' # 二枚落ち
|
58
|
-
result += '82HI22KA'
|
59
|
-
when '3' # 三枚落ち
|
60
|
-
result += '82HI22KA91KY'
|
61
|
-
when '4' # 四枚落ち
|
62
|
-
result += '82HI22KA11KY91KY'
|
63
|
-
when '5' # 五枚落ち
|
64
|
-
result += '82HI22KA81KE11KY91KY'
|
65
|
-
when '5_L' # 左五枚落ち
|
66
|
-
result += '82HI22KA21KE11KY91KY'
|
67
|
-
when '6' # 六枚落ち
|
68
|
-
result += '82HI22KA21KE81KE11KY91KY'
|
69
|
-
when '8' # 八枚落ち
|
70
|
-
result += '82HI22KA31GI71GI21KE81KE11KY91KY'
|
71
|
-
when '10' # 十枚落ち
|
72
|
-
result += '82HI22KA41KI61KI31GI71GI21KE81KE11KY91KY'
|
73
|
-
end
|
74
|
-
end
|
28
|
+
result = ""
|
29
|
+
data = initial["data"]
|
30
|
+
result += if initial["preset"] == "OTHER"
|
31
|
+
convert_board(data["board"])
|
32
|
+
else
|
33
|
+
convert_preset(initial["preset"])
|
34
|
+
end
|
75
35
|
# 持駒
|
76
|
-
if data[
|
77
|
-
|
78
|
-
data[
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
36
|
+
if data["hands"]
|
37
|
+
result += convert_hands(data["hands"], 0)
|
38
|
+
result += convert_hands(data["hands"], 1)
|
39
|
+
end
|
40
|
+
result += csa_color(data["color"]) + "\n" if data["color"]
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_hands(hands, color)
|
45
|
+
result = ""
|
46
|
+
sum = 0
|
47
|
+
hands[color].each_value { |n| sum += n }
|
48
|
+
if sum > 0
|
49
|
+
result += "P#{csa_color(color)}"
|
50
|
+
hands[color].to_a.reverse_each { |(k, v)| v.times { result += "00#{k}" } }
|
51
|
+
result += "\n"
|
91
52
|
end
|
92
|
-
result += csa_color(data['color']) + "\n" if data['color']
|
93
53
|
result
|
94
54
|
end
|
95
55
|
|
96
56
|
def convert_moves(moves)
|
97
|
-
result =
|
57
|
+
result = ""
|
98
58
|
moves.each do |move|
|
99
59
|
next if move == {}
|
100
|
-
result += convert_move(move[
|
101
|
-
result += convert_special(move[
|
102
|
-
if move[
|
103
|
-
result += "," + convert_time(move[
|
104
|
-
elsif move[
|
60
|
+
result += convert_move(move["move"]) if move["move"]
|
61
|
+
result += convert_special(move["special"], move["color"]) if move["special"]
|
62
|
+
if move["time"]
|
63
|
+
result += "," + convert_time(move["time"])
|
64
|
+
elsif move["move"] || move["special"]
|
105
65
|
result += "\n"
|
106
66
|
end
|
107
|
-
result += convert_comments(move[
|
67
|
+
result += convert_comments(move["comments"]) if move["comments"]
|
108
68
|
end
|
109
69
|
result
|
110
70
|
end
|
111
71
|
|
112
72
|
def convert_move(move)
|
113
|
-
result = csa_color(move[
|
114
|
-
result +=
|
115
|
-
|
116
|
-
else
|
117
|
-
"00"
|
118
|
-
end
|
119
|
-
result += "#{move['to']['x']}#{move['to']['y']}"
|
120
|
-
result += move['piece']
|
121
|
-
result
|
73
|
+
result = csa_color(move["color"])
|
74
|
+
result += move["from"] ? pos2str(move["from"]) : "00"
|
75
|
+
result + pos2str(move["to"]) + move["piece"]
|
122
76
|
end
|
123
77
|
|
124
|
-
def convert_special(special, color=nil)
|
78
|
+
def convert_special(special, color = nil)
|
125
79
|
result = "%"
|
126
80
|
result += csa_color(color) if color
|
127
|
-
result
|
128
|
-
result
|
81
|
+
result + special
|
129
82
|
end
|
130
83
|
|
131
84
|
def convert_time(time)
|
132
|
-
sec = time[
|
85
|
+
sec = time["now"]["m"] * 60 + time["now"]["s"]
|
133
86
|
"T#{sec}\n"
|
134
87
|
end
|
135
88
|
|
@@ -137,10 +90,62 @@ module Jkf::Converter
|
|
137
90
|
comments.map { |comment| "'#{comment}" }.join("\n") + "\n"
|
138
91
|
end
|
139
92
|
|
140
|
-
|
93
|
+
def convert_board(board)
|
94
|
+
result = ""
|
95
|
+
9.times do |y|
|
96
|
+
result += "P#{y + 1}"
|
97
|
+
9.times do |x|
|
98
|
+
piece = board[8 - x][y]
|
99
|
+
result += if piece == {}
|
100
|
+
" * "
|
101
|
+
else
|
102
|
+
csa_color(piece["color"]) + piece["kind"]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
result += "\n"
|
106
|
+
end
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
def convert_preset(preset)
|
111
|
+
"PI" +
|
112
|
+
case preset
|
113
|
+
when "HIRATE"
|
114
|
+
when "KY" # 香落ち
|
115
|
+
"11KY"
|
116
|
+
when "KY_R" # 右香落ち
|
117
|
+
"91KY"
|
118
|
+
when "KA" # 角落ち
|
119
|
+
"22KA"
|
120
|
+
when "HI" # 飛車落ち
|
121
|
+
"82HI"
|
122
|
+
when "HIKY" # 飛香落ち
|
123
|
+
"22HI11KY91KY"
|
124
|
+
when "2" # 二枚落ち
|
125
|
+
"82HI22KA"
|
126
|
+
when "3" # 三枚落ち
|
127
|
+
"82HI22KA91KY"
|
128
|
+
when "4" # 四枚落ち
|
129
|
+
"82HI22KA11KY91KY"
|
130
|
+
when "5" # 五枚落ち
|
131
|
+
"82HI22KA81KE11KY91KY"
|
132
|
+
when "5_L" # 左五枚落ち
|
133
|
+
"82HI22KA21KE11KY91KY"
|
134
|
+
when "6" # 六枚落ち
|
135
|
+
"82HI22KA21KE81KE11KY91KY"
|
136
|
+
when "8" # 八枚落ち
|
137
|
+
"82HI22KA31GI71GI21KE81KE11KY91KY"
|
138
|
+
when "10" # 十枚落ち
|
139
|
+
"82HI22KA41KI61KI31GI71GI21KE81KE11KY91KY"
|
140
|
+
end
|
141
|
+
end
|
141
142
|
|
142
143
|
def csa_color(color)
|
143
|
-
color == 0 ?
|
144
|
+
color == 0 ? "+" : "-"
|
145
|
+
end
|
146
|
+
|
147
|
+
def pos2str(pos)
|
148
|
+
"%d%d" % [pos["x"], pos["y"]]
|
144
149
|
end
|
145
150
|
|
146
151
|
def version
|
@@ -149,11 +154,11 @@ module Jkf::Converter
|
|
149
154
|
|
150
155
|
def csa_header_key(key)
|
151
156
|
{
|
152
|
-
"棋戦"
|
153
|
-
"場所"
|
157
|
+
"棋戦" => "EVENT",
|
158
|
+
"場所" => "SITE",
|
154
159
|
"開始日時" => "START_TIME",
|
155
160
|
"終了日時" => "END_TIME",
|
156
|
-
"持ち時間" => "TIME_LIMIT"
|
161
|
+
"持ち時間" => "TIME_LIMIT"
|
157
162
|
}[key] || key
|
158
163
|
end
|
159
164
|
end
|