jkf 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79e1ae754b51607fe6534b5c8c41204442af455e
4
- data.tar.gz: b61950a75a9b4c7bd38016b32a586bf7ce7d6e95
3
+ metadata.gz: cad7bbf021250fb745379dfde6cdd189ac23065f
4
+ data.tar.gz: eff17d1efc52ff07bdc58bc6d4b61afa0022a1fb
5
5
  SHA512:
6
- metadata.gz: 82c946e99c94984ba20f5af1369b3d555bf0dfea5fc27886bd0808006b91f9ae22acd29de33d71d813b1810b5a31eb978f6be92c40224887115ea05c39626589
7
- data.tar.gz: 669322bd5d08c7b6a78e887e773c90d89e20dd927e0043c16417cdadb49bbf30a4bcef2c72fb225d378e63849f27abd92df20c6051da3a0b32798e21fbae16a5
6
+ metadata.gz: 081f1b970eb509aaa33495fb14459d6a37ce7510f59d94a1ee9ea1c3b2f23319b6ccb36383029f456cfa681d3ae5e7ab164dfde4f647ae25d8ddd3d1f46a7906
7
+ data.tar.gz: 7d0bb2322d33f323f64b82350108721b2d6694a04000879a58e9d87299bc4426deed8b730c28f85288b8b54d73e7f011d41d37cbeac1e2b3f60f81e145686a18
@@ -0,0 +1,61 @@
1
+ # 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
+
4
+
5
+ jkf is json-kifu-format( https://github.com/na2hiro/json-kifu-format ) library for ruby.
6
+
7
+ ### Feature
8
+
9
+ * KIF, KI2, CSA to JKF
10
+ * JKF to KIF, KI2, CSA
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'jkf'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install jkf
27
+
28
+ ## Usage
29
+
30
+ ```ruby
31
+ kif_parser = Jkf::Parser::Kif.new
32
+ ki2_parser = Jkf::Parser::Ki2.new
33
+ csa_parser = Jkf::Parser::Csa.new
34
+ ```
35
+
36
+ ```ruby
37
+ kif_converter = Jkf::Converter::Kif.new
38
+ ki2_converter = Jkf::Converter::Ki2.new
39
+ csa_converter = Jkf::Converter::Csa.new
40
+ ```
41
+
42
+ ```ruby
43
+ jkf = kif_parser.parse(kif_str) #=> Hash
44
+ jkf = ki2_parser.parse(ki2_str) #=> Hash
45
+ jkf = csa_parser.parse(csa_str) #=> Hash
46
+ ```
47
+
48
+ ```ruby
49
+ kif = kif_converter.parse(jkf) #=> String
50
+ ki2 = ki2_converter.parse(jkf) #=> String
51
+ csa = csa_converter.parse(jkf) #=> String
52
+ ```
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at https://github.com/iyuuya/jkf.
57
+
58
+ ## License
59
+
60
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
61
+
data/README.md CHANGED
@@ -1,42 +1,62 @@
1
1
  # Jkf
2
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
- 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
-
6
- TODO: Delete this and the text above, and describe your gem
4
+ jkfはJSON棋譜フォーマット( https://github.com/na2hiro/json-kifu-format )をRubyに移植したものです。
5
+ KIF, KI2, CSAをパースしJKFへ変換、JKFからKIF, KI2, CSAへの変換に対応しています。
7
6
 
8
7
  ## Installation
9
8
 
10
- Add this line to your application's Gemfile:
9
+ アプリケーションにインストールする場合(bundlerを使用する場合)、Gemfileに以下のように記述してください。
11
10
 
12
11
  ```ruby
13
12
  gem 'jkf'
14
13
  ```
15
14
 
16
- And then execute:
15
+ さらにbundleコマンドを実行することでインストールできます。
17
16
 
18
17
  $ bundle
19
18
 
20
- Or install it yourself as:
19
+ または、gem installコマンドを使って直接インストールすることもできます。
21
20
 
22
21
  $ gem install jkf
23
22
 
24
23
  ## Usage
25
24
 
26
- TODO: Write usage instructions here
25
+ KIF, KI2, CSAそれぞれParserとConverterが用意してあります。
27
26
 
28
- ## Development
27
+ ```ruby
28
+ kif_parser = Jkf::Parser::Kif.new
29
+ ki2_parser = Jkf::Parser::Ki2.new
30
+ csa_parser = Jkf::Parser::Csa.new
31
+ ```
29
32
 
30
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec jkf` to use the gem in this directory, ignoring other installed copies of this gem.
33
+ ```ruby
34
+ kif_converter = Jkf::Converter::Kif.new
35
+ ki2_converter = Jkf::Converter::Ki2.new
36
+ csa_converter = Jkf::Converter::Csa.new
37
+ ```
31
38
 
32
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+ `parser#parse(str)`でjkfへの変換、`#convert(jkf)`でjkfから各フォーマットへ変換できます。
33
40
 
34
- ## Contributing
41
+ ```ruby
42
+ jkf = kif_parser.parse(kif_str) #=> Hash
43
+ jkf = ki2_parser.parse(ki2_str) #=> Hash
44
+ jkf = csa_parser.parse(csa_str) #=> Hash
45
+ ```
46
+
47
+ ```ruby
48
+ kif = kif_converter.parse(jkf) #=> String
49
+ ki2 = ki2_converter.parse(jkf) #=> String
50
+ csa = csa_converter.parse(jkf) #=> String
51
+ ```
35
52
 
36
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/jkf.
53
+ ## Contributing
37
54
 
55
+ バグレポートやプルリクエストはGithubでよろしくお願いします。
56
+ https://github.com/iyuuya/jkf.
38
57
 
39
58
  ## License
40
59
 
41
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
60
+ ライセンスはMITです。
61
+ [MIT License](http://opensource.org/licenses/MIT).
42
62
 
data/lib/jkf.rb CHANGED
@@ -3,10 +3,17 @@ require "jkf/version"
3
3
  require "jkf/parser"
4
4
  require "jkf/converter"
5
5
 
6
+ # JSON Kifu Format
6
7
  module Jkf
8
+ # raise when unsupport file type
7
9
  class FileTypeError < StandardError; end
8
10
 
9
11
  class << self
12
+ # ファイルからパースします。拡張子でフォーマットの判定をします。
13
+ #
14
+ # @param [String] filename
15
+ #
16
+ # @return [String] KIF, KI2, CSA, JKF(JSON)
10
17
  def parse_file(filename, encoding: "Shift_JIS")
11
18
  parser = case ::File.extname(filename)
12
19
  when /kif/
@@ -17,11 +24,18 @@ module Jkf
17
24
  ::Jkf::Parser::Csa.new
18
25
  when /jkf|json/
19
26
  JSON
27
+ else
28
+ raise FileTypeError
20
29
  end
21
30
  str = File.read(File.expand_path(filename), encoding: encoding).toutf8
22
31
  parser.parse(str)
23
32
  end
24
33
 
34
+ # 文字列からパースします。各パーサでパースに試みて成功した場合結果を返します。
35
+ #
36
+ # @param [String] str
37
+ #
38
+ # @return [Hash] JKF
25
39
  def parse(str)
26
40
  parsers = [::Jkf::Parser::Kif.new, ::Jkf::Parser::Ki2.new, ::Jkf::Parser::Csa.new, JSON]
27
41
 
@@ -1,5 +1,7 @@
1
1
  module Jkf
2
+ # Define converter namespace
2
3
  module Converter
4
+ # Convert error
3
5
  class ConvertError < StandardError; end
4
6
  end
5
7
  end
@@ -1,5 +1,10 @@
1
1
  module Jkf::Converter
2
+ # Base of Converter
2
3
  class Base
4
+ # start convert
5
+ #
6
+ # @param [String, Hash] jkf
7
+ # @return [String] kif or ki2 or csa text
3
8
  def convert(jkf)
4
9
  jkf = jkf.is_a?(Hash) ? jkf : JSON.parse(jkf)
5
10
  convert_root(jkf)
@@ -1,7 +1,10 @@
1
1
  module Jkf::Converter
2
+ # CSA v2.2 Converter
2
3
  class Csa < Base
3
4
  VERSION = "2.2".freeze
4
5
 
6
+ protected
7
+
5
8
  def convert_root(jkf)
6
9
  result = version
7
10
  result += convert_information(jkf["header"]) if jkf["header"]
@@ -10,8 +13,6 @@ module Jkf::Converter
10
13
  result
11
14
  end
12
15
 
13
- protected
14
-
15
16
  def convert_information(header)
16
17
  result = ""
17
18
  if header["先手"] || header["下手"]
@@ -1,9 +1,10 @@
1
1
  module Jkf::Converter
2
+ # KI2 Converter
2
3
  class Ki2 < Base
3
- protected
4
-
5
4
  include Kifuable
6
5
 
6
+ protected
7
+
7
8
  def convert_root(jkf)
8
9
  reset!
9
10
  setup_players!(jkf)
@@ -1,4 +1,5 @@
1
1
  module Jkf::Converter
2
+ # KIF Converter
2
3
  class Kif < Base
3
4
  protected
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Jkf::Converter
2
+ # Intersection of KIF and KI2
2
3
  module Kifuable
3
4
  protected
4
5
 
@@ -1,5 +1,7 @@
1
1
  module Jkf
2
+ # Define parser namespace
2
3
  module Parser
4
+ # Parse error
3
5
  class ParseError < StandardError; end
4
6
  end
5
7
  end
@@ -1,5 +1,11 @@
1
1
  module Jkf::Parser
2
+ # Base of Parser
2
3
  class Base
4
+ # start parse
5
+ #
6
+ # @param [String] input
7
+ #
8
+ # @return [Hash] JKF
3
9
  def parse(input)
4
10
  @input = input.clone
5
11
 
@@ -29,6 +35,7 @@ module Jkf::Parser
29
35
 
30
36
  def failed?; !success?; end
31
37
 
38
+ # match regexp
32
39
  def match_regexp(reg)
33
40
  ret = nil
34
41
  if matched = reg.match(@input[@current_pos])
@@ -41,6 +48,7 @@ module Jkf::Parser
41
48
  ret
42
49
  end
43
50
 
51
+ # match string
44
52
  def match_str(str)
45
53
  ret = nil
46
54
  if @input[@current_pos, str.size] == str
@@ -53,10 +61,12 @@ module Jkf::Parser
53
61
  ret
54
62
  end
55
63
 
64
+ # match space
56
65
  def match_space
57
66
  match_str(" ")
58
67
  end
59
68
 
69
+ # match space one or more
60
70
  def match_spaces
61
71
  stack = []
62
72
  matched = match_space
@@ -67,10 +77,12 @@ module Jkf::Parser
67
77
  stack
68
78
  end
69
79
 
80
+ # match digit
70
81
  def match_digit
71
82
  match_regexp(/^\d/)
72
83
  end
73
84
 
85
+ # match digits
74
86
  def match_digits
75
87
  stack = []
76
88
  matched = match_digit
@@ -81,6 +93,7 @@ module Jkf::Parser
81
93
  stack
82
94
  end
83
95
 
96
+ # match digit one ore more
84
97
  def match_digits!
85
98
  matched = match_digits
86
99
  if matched.empty?
@@ -90,6 +103,7 @@ module Jkf::Parser
90
103
  end
91
104
  end
92
105
 
106
+ # record failure
93
107
  def fail(expected)
94
108
  return if @current_pos < @max_fail_pos
95
109
 
@@ -1,7 +1,11 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Jkf::Parser
4
+ # CSA Parser
4
5
  class Csa < Base
6
+ protected
7
+
8
+ # kifu : csa2 | csa1
5
9
  def parse_root
6
10
  @input += "\n" unless @input[-1] =~ /\n|\r|,/ # FIXME
7
11
  s0 = parse_csa2
@@ -9,6 +13,7 @@ module Jkf::Parser
9
13
  s0
10
14
  end
11
15
 
16
+ # csa2 : version22 information? initialboard moves?
12
17
  def parse_csa2
13
18
  s0 = @current_pos
14
19
  if parse_version22 != :failed
@@ -38,6 +43,7 @@ module Jkf::Parser
38
43
  s0
39
44
  end
40
45
 
46
+ # version22 : comment* "V2.2" nl
41
47
  def parse_version22
42
48
  s0 = @current_pos
43
49
  s1 = parse_comments
@@ -57,6 +63,7 @@ module Jkf::Parser
57
63
  s0
58
64
  end
59
65
 
66
+ # information : players? headers
60
67
  def parse_information
61
68
  s0 = @current_pos
62
69
  s1 = parse_players
@@ -72,6 +79,7 @@ module Jkf::Parser
72
79
  s0
73
80
  end
74
81
 
82
+ # headers : header*
75
83
  def parse_headers
76
84
  s0 = @current_pos
77
85
  s1 = []
@@ -91,6 +99,7 @@ module Jkf::Parser
91
99
  s0
92
100
  end
93
101
 
102
+ # header : comment* "$" [^:]+ ":" nonls nl
94
103
  def parse_header
95
104
  s0 = @current_pos
96
105
  parse_comments
@@ -130,6 +139,7 @@ module Jkf::Parser
130
139
  s0
131
140
  end
132
141
 
142
+ # csa1 : players? initialboard? moves
133
143
  def parse_csa1
134
144
  s0 = @current_pos
135
145
  s1 = parse_players
@@ -154,6 +164,7 @@ module Jkf::Parser
154
164
  s0
155
165
  end
156
166
 
167
+ # players : comment* ("N+" nonls nl)? comment* ("N-" nonls nl)?
157
168
  def parse_players
158
169
  s0 = @current_pos
159
170
  parse_comments
@@ -193,6 +204,7 @@ module Jkf::Parser
193
204
  s0
194
205
  end
195
206
 
207
+ # initialboard : comment* (hirate | ikkatsu | "") komabetsu comment* teban nl
196
208
  def parse_initial_board
197
209
  s0 = @current_pos
198
210
  parse_comments
@@ -244,6 +256,7 @@ module Jkf::Parser
244
256
  end
245
257
  end
246
258
 
259
+ # hirate : "PI" xypiece* nl
247
260
  def parse_hirate
248
261
  s0 = @current_pos
249
262
  if match_str("PI") != :failed
@@ -273,6 +286,7 @@ module Jkf::Parser
273
286
  s0
274
287
  end
275
288
 
289
+ # ikkatsu : ikkatsuline+
276
290
  def parse_ikkatsu
277
291
  s0 = @current_pos
278
292
  s2 = parse_ikkatsu_line
@@ -303,10 +317,11 @@ module Jkf::Parser
303
317
  s0
304
318
  end
305
319
 
320
+ # ikkatsuline : "P" [1-9] masu+ nl
306
321
  def parse_ikkatsu_line
307
322
  s0 = @current_pos
308
323
  if match_str("P") != :failed
309
- if match_regexp(/^[1-9]/) != :failed
324
+ if match_digit != :failed
310
325
  s4 = parse_masu
311
326
  if s4 != :failed
312
327
  s3 = []
@@ -341,6 +356,7 @@ module Jkf::Parser
341
356
  s0
342
357
  end
343
358
 
359
+ # masu : teban piece | " * "
344
360
  def parse_masu
345
361
  s0 = @current_pos
346
362
  s1 = parse_teban
@@ -368,6 +384,7 @@ module Jkf::Parser
368
384
  s0
369
385
  end
370
386
 
387
+ # komabetsu : komabetsuline*
371
388
  def parse_komabetsu
372
389
  s0 = @current_pos
373
390
  s1 = []
@@ -380,6 +397,7 @@ module Jkf::Parser
380
397
  transform_komabetsu_lines(s1)
381
398
  end
382
399
 
400
+ # komabetsuline : "P" teban xypiece+ nl
383
401
  def parse_komabetsu_line
384
402
  s0 = @current_pos
385
403
  if match_str("P") != :failed
@@ -418,6 +436,7 @@ module Jkf::Parser
418
436
  s0
419
437
  end
420
438
 
439
+ # moves : firstboard move* comment*
421
440
  def parse_moves
422
441
  s0 = @current_pos
423
442
  s1 = parse_firstboard
@@ -438,6 +457,7 @@ module Jkf::Parser
438
457
  s0
439
458
  end
440
459
 
460
+ # firstboard : comment*
441
461
  def parse_firstboard
442
462
  s0 = @current_pos
443
463
  s1 = parse_comments
@@ -445,6 +465,7 @@ module Jkf::Parser
445
465
  s1.empty? ? {} : { "comments" => s1 }
446
466
  end
447
467
 
468
+ # move : (normalmove | specialmove) time? comment*
448
469
  def parse_move
449
470
  s0 = @current_pos
450
471
  s1 = parse_normal_move
@@ -472,6 +493,7 @@ module Jkf::Parser
472
493
  s0
473
494
  end
474
495
 
496
+ # normalmove : teban xy xy piece nl
475
497
  def parse_normal_move
476
498
  s0 = @current_pos
477
499
  s1 = parse_teban
@@ -512,6 +534,7 @@ module Jkf::Parser
512
534
  s0
513
535
  end
514
536
 
537
+ # specialmove : "%" [-+_A-Z]+ nl
515
538
  def parse_special_move
516
539
  s0 = @current_pos
517
540
  s1 = match_str("%")
@@ -545,6 +568,7 @@ module Jkf::Parser
545
568
  s0
546
569
  end
547
570
 
571
+ # teban : "+" | "-"
548
572
  def parse_teban
549
573
  s0 = @current_pos
550
574
  s1 = match_str("+")
@@ -565,6 +589,7 @@ module Jkf::Parser
565
589
  s0
566
590
  end
567
591
 
592
+ # comment : "'" nonls nl
568
593
  def parse_comment
569
594
  s0 = @current_pos
570
595
  if match_str("'") != :failed
@@ -582,6 +607,7 @@ module Jkf::Parser
582
607
  end
583
608
  end
584
609
 
610
+ # comments : comment*
585
611
  def parse_comments
586
612
  stack = []
587
613
  matched = parse_comment
@@ -592,6 +618,7 @@ module Jkf::Parser
592
618
  stack
593
619
  end
594
620
 
621
+ # time : "T" [0-9]* nl
595
622
  def parse_time
596
623
  s0 = @current_pos
597
624
  if match_str("T") != :failed
@@ -610,6 +637,7 @@ module Jkf::Parser
610
637
  s0
611
638
  end
612
639
 
640
+ # xy : [0-9] [0-9]
613
641
  def parse_xy
614
642
  s0 = @current_pos
615
643
  s1 = match_digit
@@ -629,6 +657,7 @@ module Jkf::Parser
629
657
  s0
630
658
  end
631
659
 
660
+ # piece : [A-Z] [A-Z]
632
661
  def parse_piece
633
662
  s0 = @current_pos
634
663
  s1 = match_regexp(/^[A-Z]/)
@@ -648,6 +677,7 @@ module Jkf::Parser
648
677
  s0
649
678
  end
650
679
 
680
+ # xypiece : xy piece
651
681
  def parse_xy_piece
652
682
  s0 = @current_pos
653
683
  s1 = parse_xy
@@ -667,6 +697,7 @@ module Jkf::Parser
667
697
  s0
668
698
  end
669
699
 
700
+ # nl : ("\r"? "\n") | " "* ","
670
701
  def parse_nl
671
702
  s0 = @current_pos
672
703
  s1 = match_str("\r")
@@ -692,10 +723,12 @@ module Jkf::Parser
692
723
  s0
693
724
  end
694
725
 
726
+ # nonl : [^\r\n]
695
727
  def parse_nonl
696
728
  match_regexp(/^[^\r\n]/)
697
729
  end
698
730
 
731
+ # nonls : nonl*
699
732
  def parse_nonls
700
733
  stack = []
701
734
  matched = parse_nonl
@@ -706,8 +739,7 @@ module Jkf::Parser
706
739
  stack
707
740
  end
708
741
 
709
- protected
710
-
742
+ # lines to jkf
711
743
  def transform_komabetsu_lines(lines)
712
744
  board = generate_empty_board
713
745
  hands = [
@@ -737,6 +769,7 @@ module Jkf::Parser
737
769
  { "preset" => "OTHER", "data" => { "board" => board, "hands" => hands } }
738
770
  end
739
771
 
772
+ # return empty board jkf
740
773
  def generate_empty_board
741
774
  board = []
742
775
  9.times do |_i|
@@ -749,12 +782,14 @@ module Jkf::Parser
749
782
  board
750
783
  end
751
784
 
785
+ # sec to time(m, s)
752
786
  def sec2time(sec)
753
787
  s = sec % 60
754
788
  m = (sec - s) / 60
755
789
  { "m" => m, "s" => s }
756
790
  end
757
791
 
792
+ # return hirate board jkf
758
793
  def get_hirate
759
794
  [
760
795
  [{ "color" => 1, "kind" => "KY" }, {}, { "color" => 1, "kind" => "FU" }, {}, {}, {},
@@ -780,6 +815,7 @@ module Jkf::Parser
780
815
  ]
781
816
  end
782
817
 
818
+ # normalize header key
783
819
  def normalize_header_key(key)
784
820
  {
785
821
  "EVENT" => "棋戦",
@@ -1,9 +1,13 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Jkf::Parser
4
+ # KI2 Parser
4
5
  class Ki2 < Base
5
6
  include Kifuable
6
7
 
8
+ protected
9
+
10
+ # kifu : header* initialboard? header* moves fork*
7
11
  def parse_root
8
12
  s0 = @current_pos
9
13
  s1 = []
@@ -42,6 +46,7 @@ module Jkf::Parser
42
46
  s0
43
47
  end
44
48
 
49
+ # header : [^:\r\n]+ ":" nonls nl+ | header_teban
45
50
  def parse_header
46
51
  s0 = @current_pos
47
52
  s2 = match_regexp(/^[^*:\r\n]/)
@@ -86,9 +91,10 @@ module Jkf::Parser
86
91
  s0
87
92
  end
88
93
 
94
+ # header_teban : [先後上下] "手番" nl
89
95
  def parse_header_teban
90
96
  s0 = @current_pos
91
- s1 = match_regexp(/^[先後上下]/)
97
+ s1 = parse_turn
92
98
  if s1 != :failed
93
99
  s2 = match_str("手番")
94
100
  if s2 != :failed
@@ -110,6 +116,7 @@ module Jkf::Parser
110
116
  end
111
117
  end
112
118
 
119
+ # moves : firstboard : move* result?
113
120
  def parse_moves
114
121
  s0 = @current_pos
115
122
  s1 = parse_firstboard
@@ -135,6 +142,7 @@ module Jkf::Parser
135
142
  s0
136
143
  end
137
144
 
145
+ # firstboard : comment* pointer?
138
146
  def parse_firstboard
139
147
  s0 = @current_pos
140
148
  s1 = []
@@ -149,6 +157,7 @@ module Jkf::Parser
149
157
  s0
150
158
  end
151
159
 
160
+ # move : line comment* pointer? (nl | " ")*
152
161
  def parse_move
153
162
  s0 = @current_pos
154
163
  s1 = parse_line
@@ -182,6 +191,7 @@ module Jkf::Parser
182
191
  s0
183
192
  end
184
193
 
194
+ # line : [▲△] fugou (nl / " ")*
185
195
  def parse_line
186
196
  s0 = @current_pos
187
197
  s1 = match_regexp(/^[▲△]/)
@@ -214,6 +224,7 @@ module Jkf::Parser
214
224
  s0
215
225
  end
216
226
 
227
+ # fugou : place piece soutai? dousa? ("成" | "不成")? "打"?
217
228
  def parse_fugou
218
229
  s0 = @current_pos
219
230
  s1 = parse_place
@@ -241,6 +252,7 @@ module Jkf::Parser
241
252
  end
242
253
  end
243
254
 
255
+ # place : num numkan
244
256
  def parse_place
245
257
  s0 = @current_pos
246
258
  s1 = parse_num
@@ -271,15 +283,17 @@ module Jkf::Parser
271
283
  s0
272
284
  end
273
285
 
274
-
286
+ # soutai : [左直右]
275
287
  def parse_soutai
276
288
  match_regexp(/^[左直右]/)
277
289
  end
278
290
 
291
+ # dousa : [上寄引]
279
292
  def parse_dousa
280
293
  match_regexp(/^[上寄引]/)
281
294
  end
282
295
 
296
+ # "*" nonls nl
283
297
  def parse_comment
284
298
  s0 = @current_pos
285
299
  if match_str("*") != :failed
@@ -298,6 +312,7 @@ module Jkf::Parser
298
312
  s0
299
313
  end
300
314
 
315
+ # fork : "変化:" " "* [0-9]+ "手" nl moves
301
316
  def parse_fork
302
317
  s0 = @current_pos
303
318
  if match_str("変化:") != :failed
@@ -333,12 +348,12 @@ module Jkf::Parser
333
348
  s0
334
349
  end
335
350
 
351
+ # turn : [先後上下]
336
352
  def parse_turn
337
353
  match_regexp(/^[先後上下]/)
338
354
  end
339
355
 
340
- protected
341
-
356
+ # transform to jkf
342
357
  def transform_root(headers, ini, headers2, moves, forks)
343
358
  ret = { "header" => {}, "moves" => moves }
344
359
  headers.compact.each { |h| ret["header"][h["k"]] = h["v"] }
@@ -354,6 +369,7 @@ module Jkf::Parser
354
369
  ret
355
370
  end
356
371
 
372
+ # transfrom fugou to jkf
357
373
  def transform_fugou(pl, pi, sou, dou, pro, da)
358
374
  ret = { "piece" => pi }
359
375
  if pl["same"]
@@ -371,6 +387,7 @@ module Jkf::Parser
371
387
  ret
372
388
  end
373
389
 
390
+ # relative string to jkf
374
391
  def soutai2relative(str)
375
392
  {
376
393
  "左" => "L",
@@ -379,6 +396,7 @@ module Jkf::Parser
379
396
  }[str] || ""
380
397
  end
381
398
 
399
+ # movement string to jkf
382
400
  def dousa2relative(str)
383
401
  {
384
402
  "上" => "U",
@@ -387,6 +405,7 @@ module Jkf::Parser
387
405
  }[str] || ""
388
406
  end
389
407
 
408
+ # generate motigoma
390
409
  def make_hand(str)
391
410
  ret = { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 }
392
411
  return ret if str.empty?
@@ -399,6 +418,7 @@ module Jkf::Parser
399
418
  ret
400
419
  end
401
420
 
421
+ # check eos
402
422
  def eos?
403
423
  @input[@current_pos].nil?
404
424
  end
@@ -1,9 +1,13 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Jkf::Parser
4
+ # KIF Parser
4
5
  class Kif < Base
5
6
  include Kifuable
6
7
 
8
+ protected
9
+
10
+ # kifu : skipline* header* initialboard? header* split? moves fork* nl?
7
11
  def parse_root
8
12
  @input += "\n" unless @input.end_with?("\n")
9
13
 
@@ -49,6 +53,9 @@ module Jkf::Parser
49
53
  s0
50
54
  end
51
55
 
56
+ # header : [^:\r\n]+ ":" nonls nl
57
+ # | turn "手番" nl
58
+ # | "盤面回転" nl
52
59
  def parse_header
53
60
  s0 = @current_pos
54
61
  s2 = match_regexp(/^[^:\r\n]/)
@@ -120,10 +127,12 @@ module Jkf::Parser
120
127
  s0
121
128
  end
122
129
 
130
+ # turn : [先後上下]
123
131
  def parse_turn
124
- match_regexp(/[先後上下]/)
132
+ match_regexp(/^[先後上下]/)
125
133
  end
126
134
 
135
+ # split : "手数----指手--" "-------消費時間--"? nl
127
136
  def parse_split
128
137
  s0 = @current_pos
129
138
  s1 = match_str("手数----指手--")
@@ -144,6 +153,7 @@ module Jkf::Parser
144
153
  s0
145
154
  end
146
155
 
156
+ # moves : firstboard split? move* result?
147
157
  def parse_moves
148
158
  s0 = @current_pos
149
159
  s1 = parse_firstboard
@@ -165,6 +175,7 @@ module Jkf::Parser
165
175
  s0
166
176
  end
167
177
 
178
+ # firstboard : comment* pointer?
168
179
  def parse_firstboard
169
180
  s0 = @current_pos
170
181
  s1 = []
@@ -179,6 +190,7 @@ module Jkf::Parser
179
190
  s0
180
191
  end
181
192
 
193
+ # move : line comment* pointer?
182
194
  def parse_move
183
195
  s0 = @current_pos
184
196
  s1 = parse_line
@@ -199,6 +211,7 @@ module Jkf::Parser
199
211
  s0
200
212
  end
201
213
 
214
+ # line : " "* te " "* (fugou from | [^\r\n ]*) " "* time? "+"? nl
202
215
  def parse_line
203
216
  s0 = @current_pos
204
217
  match_spaces
@@ -254,10 +267,12 @@ module Jkf::Parser
254
267
  s0
255
268
  end
256
269
 
270
+ # te : [0-9]+
257
271
  def parse_te
258
272
  match_digits!
259
273
  end
260
274
 
275
+ # fugou : place piece "成"?
261
276
  def parse_fugou
262
277
  s0 = @current_pos
263
278
  s1 = parse_place
@@ -279,6 +294,7 @@ module Jkf::Parser
279
294
  s0
280
295
  end
281
296
 
297
+ # place : num numkan | "同 "
282
298
  def parse_place
283
299
  s0 = @current_pos
284
300
  s1 = parse_num
@@ -307,6 +323,7 @@ module Jkf::Parser
307
323
  s0
308
324
  end
309
325
 
326
+ # from : "打" | "(" [1-9] [1-9] ")"
310
327
  def parse_from
311
328
  s0 = @current_pos
312
329
  s1 = match_str("打")
@@ -345,16 +362,20 @@ module Jkf::Parser
345
362
  s0
346
363
  end
347
364
 
365
+ # time : "(" " "* ms " "* "/" " "* (hms | ms) " "* ")"
348
366
  def parse_time
349
367
  s0 = @current_pos
350
368
  if match_str("(") != :failed
351
369
  match_spaces
352
370
  s3 = parse_ms
353
371
  if s3 != :failed
372
+ match_spaces
354
373
  if match_str("/") != :failed
374
+ match_spaces
355
375
  s5 = parse_hms
356
376
  s5 = parse_ms(with_hour: true) if s5 == :failed
357
377
  if s5 != :failed
378
+ match_spaces
358
379
  if match_str(")") != :failed
359
380
  @reported_pos = s0
360
381
  s0 = { "now" => s3, "total" => s5 }
@@ -381,6 +402,7 @@ module Jkf::Parser
381
402
  s0
382
403
  end
383
404
 
405
+ # hms : [0-9]+ ":" [0-9]+ ":" [0-9]+
384
406
  def parse_hms
385
407
  s0 = @current_pos
386
408
  s1 = match_digits!
@@ -417,6 +439,7 @@ module Jkf::Parser
417
439
  s0
418
440
  end
419
441
 
442
+ # ms : [0-9]+ ":" [0-9]+
420
443
  def parse_ms(with_hour: false)
421
444
  s0 = @current_pos
422
445
  s1 = match_digits!
@@ -449,6 +472,7 @@ module Jkf::Parser
449
472
  s0
450
473
  end
451
474
 
475
+ # comment : "*" nonls nl | "&" nonls nl
452
476
  def parse_comment
453
477
  s0 = @current_pos
454
478
  if match_str("*") != :failed
@@ -484,6 +508,7 @@ module Jkf::Parser
484
508
  s0
485
509
  end
486
510
 
511
+ # fork : "変化:" " "* [0-9]+ "手" nl moves
487
512
  def parse_fork
488
513
  s0 = @current_pos
489
514
  if match_str("変化:") != :failed
@@ -519,8 +544,7 @@ module Jkf::Parser
519
544
  s0
520
545
  end
521
546
 
522
- protected
523
-
547
+ # transfrom to jkf
524
548
  def transform_root(headers, ini, headers2, moves, forks)
525
549
  ret = { "header" => {}, "moves" => moves }
526
550
  headers.compact.each { |h| ret["header"][h["k"]] = h["v"] }
@@ -539,6 +563,7 @@ module Jkf::Parser
539
563
  ret
540
564
  end
541
565
 
566
+ # transform move to jkf
542
567
  def transform_move(line, c)
543
568
  ret = {}
544
569
  ret["comments"] = c if !c.empty?
@@ -551,6 +576,7 @@ module Jkf::Parser
551
576
  ret
552
577
  end
553
578
 
579
+ # transform teban-fugou-from to jkf
554
580
  def transform_teban_fugou_from(teban, fugou, from)
555
581
  ret = { "color" => teban2color(teban.join), "piece" => fugou["piece"] }
556
582
  if fugou["to"]
@@ -563,6 +589,7 @@ module Jkf::Parser
563
589
  ret
564
590
  end
565
591
 
592
+ # special string to csa
566
593
  def special2csa(str)
567
594
  {
568
595
  "中断" => "CHUDAN",
@@ -577,11 +604,13 @@ module Jkf::Parser
577
604
  }[str] || (raise ParseError)
578
605
  end
579
606
 
607
+ # teban to color
580
608
  def teban2color(teban)
581
609
  teban = teban.to_i unless teban.is_a? Fixnum
582
610
  (teban + 1) % 2
583
611
  end
584
612
 
613
+ # generate motigoma
585
614
  def make_hand(str)
586
615
  # Kifu for iPhoneは半角スペース区切り
587
616
  ret = { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 }
@@ -595,6 +624,7 @@ module Jkf::Parser
595
624
  ret
596
625
  end
597
626
 
627
+ # exchange sente gote
598
628
  def reverse_color(moves)
599
629
  moves.each do |move|
600
630
  if move["move"] && move["move"]["color"]
@@ -1,5 +1,9 @@
1
1
  module Jkf::Parser
2
+ # Intersection of KIF and KI2
2
3
  module Kifuable
4
+ protected
5
+
6
+ # initialboard : (" " nonls nl)? ("+" nonls nl)? ikkatsuline+ ("+" nonls nl)?
3
7
  def parse_initialboard
4
8
  s0 = s1 = @current_pos
5
9
  if match_space != :failed
@@ -42,6 +46,7 @@ module Jkf::Parser
42
46
  end
43
47
  end
44
48
 
49
+ # ikkatsuline : "|" masu:masu+ "|" nonls! nl
45
50
  def parse_ikkatsuline
46
51
  s0 = @current_pos
47
52
  if match_str("|") != :failed
@@ -86,6 +91,7 @@ module Jkf::Parser
86
91
  s0
87
92
  end
88
93
 
94
+ # masu : teban piece | " ・"
89
95
  def parse_masu
90
96
  s0 = @current_pos
91
97
  s1 = parse_teban
@@ -115,6 +121,7 @@ module Jkf::Parser
115
121
  s0
116
122
  end
117
123
 
124
+ # teban : (" " | "+" | "^") | ("v" | "V")
118
125
  def parse_teban
119
126
  s0 = @current_pos
120
127
  s1 = match_space
@@ -140,6 +147,7 @@ module Jkf::Parser
140
147
  s0
141
148
  end
142
149
 
150
+ # pointer : "&" nonls nl
143
151
  def parse_pointer
144
152
  s0 = @current_pos
145
153
  s1 = match_str("&")
@@ -159,6 +167,29 @@ module Jkf::Parser
159
167
  s0
160
168
  end
161
169
 
170
+ # num : [123456789]
171
+ def parse_num
172
+ s0 = @current_pos
173
+ s1 = match_regexp(/^[123456789]/)
174
+ if s1 != :failed
175
+ @reported_pos = s0
176
+ s1 = zen2n(s1)
177
+ end
178
+ s1
179
+ end
180
+
181
+ # numkan : [一二三四五六七八九]
182
+ def parse_numkan
183
+ s0 = @current_pos
184
+ s1 = match_regexp(/^[一二三四五六七八九]/)
185
+ if s1 != :failed
186
+ @reported_pos = s0
187
+ s1 = kan2n(s1)
188
+ end
189
+ s1
190
+ end
191
+
192
+ # piece : "成"? [歩香桂銀金角飛王玉と杏圭全馬竜龍]
162
193
  def parse_piece
163
194
  s0 = @current_pos
164
195
  s1 = match_str("成")
@@ -173,6 +204,11 @@ module Jkf::Parser
173
204
  end
174
205
  end
175
206
 
207
+ # result : "まで" [0-9]+ "手" (
208
+ # "で" (turn "手の" (result_toryo | result_illegal)) |
209
+ # result_timeup | result_chudan | result_jishogi |
210
+ # result_sennichite | result_tsumi | result_fuzumi
211
+ # ) nl
176
212
  def parse_result
177
213
  s0 = @current_pos
178
214
  if match_str("まで") != :failed
@@ -246,6 +282,7 @@ module Jkf::Parser
246
282
  end
247
283
  end
248
284
 
285
+ # result_toryo : "勝ち"
249
286
  def parse_result_toryo
250
287
  s0 = @current_pos
251
288
  s1 = match_str("勝ち")
@@ -258,6 +295,7 @@ module Jkf::Parser
258
295
  end
259
296
  end
260
297
 
298
+ # result_illegal : "反則" ("勝ち" | "負け")
261
299
  def parse_result_illegal
262
300
  s0 = @current_pos
263
301
  if match_str("反則") != :failed
@@ -290,6 +328,7 @@ module Jkf::Parser
290
328
  end
291
329
  end
292
330
 
331
+ # result_timeup : "で時間切れにより" turn "手の勝ち"
293
332
  def parse_result_timeup
294
333
  s0 = @current_pos
295
334
  if match_str("で時間切れにより") != :failed
@@ -311,6 +350,7 @@ module Jkf::Parser
311
350
  end
312
351
  end
313
352
 
353
+ # result_chudan : "で中断"
314
354
  def parse_result_chudan
315
355
  s0 = @current_pos
316
356
  s1 = match_str("で中断")
@@ -323,6 +363,7 @@ module Jkf::Parser
323
363
  end
324
364
  end
325
365
 
366
+ # result_jishogi : "で持将棋"
326
367
  def parse_result_jishogi
327
368
  s0 = @current_pos
328
369
  s1 = match_str("で持将棋")
@@ -335,6 +376,7 @@ module Jkf::Parser
335
376
  end
336
377
  end
337
378
 
379
+ # result_sennichite : "で千日手"
338
380
  def parse_result_sennichite
339
381
  s0 = @current_pos
340
382
  s1 = match_str("で千日手")
@@ -347,6 +389,7 @@ module Jkf::Parser
347
389
  end
348
390
  end
349
391
 
392
+ # result_tsumi : "で"? "詰" "み"?
350
393
  def parse_result_tsumi
351
394
  s0 = @current_pos
352
395
  match_str("で")
@@ -360,6 +403,7 @@ module Jkf::Parser
360
403
  end
361
404
  end
362
405
 
406
+ # result_fuzumi : "で不詰"
363
407
  def parse_result_fuzumi
364
408
  s0 = @current_pos
365
409
  s1 = match_str("で不詰")
@@ -372,6 +416,7 @@ module Jkf::Parser
372
416
  end
373
417
  end
374
418
 
419
+ # skipline : "#" nonls newline
375
420
  def parse_skipline
376
421
  s0 = @current_pos
377
422
  s1 = match_str("#")
@@ -391,30 +436,12 @@ module Jkf::Parser
391
436
  s0
392
437
  end
393
438
 
394
- def parse_num
395
- s0 = @current_pos
396
- s1 = match_regexp(/^[123456789]/)
397
- if s1 != :failed
398
- @reported_pos = s0
399
- s1 = zen2n(s1)
400
- end
401
- s1
402
- end
403
-
404
- def parse_numkan
405
- s0 = @current_pos
406
- s1 = match_regexp(/^[一二三四五六七八九]/)
407
- if s1 != :failed
408
- @reported_pos = s0
409
- s1 = kan2n(s1)
410
- end
411
- s1
412
- end
413
-
439
+ # whitespace : " " | "\t"
414
440
  def parse_whitespace
415
441
  match_regexp(/^[ \t]/)
416
442
  end
417
443
 
444
+ # newline : whitespace* ("\n" | "\r" "\n"?)
418
445
  def parse_newline
419
446
  s0 = @current_pos
420
447
  s1 = []
@@ -444,6 +471,7 @@ module Jkf::Parser
444
471
  end
445
472
  end
446
473
 
474
+ # nl : newline+ skipline*
447
475
  def parse_nl
448
476
  s0 = @current_pos
449
477
  s2 = parse_newline
@@ -470,10 +498,12 @@ module Jkf::Parser
470
498
  end
471
499
  end
472
500
 
501
+ # nonl :
473
502
  def parse_nonl
474
503
  match_regexp(/^[^\r\n]/)
475
504
  end
476
505
 
506
+ # nonls : nonl*
477
507
  def parse_nonls
478
508
  stack = []
479
509
  matched = parse_nonl
@@ -484,6 +514,7 @@ module Jkf::Parser
484
514
  stack
485
515
  end
486
516
 
517
+ # nonls! : nonl+
487
518
  def parse_nonls!
488
519
  matched = parse_nonls
489
520
  if matched.empty?
@@ -493,8 +524,7 @@ module Jkf::Parser
493
524
  end
494
525
  end
495
526
 
496
- protected
497
-
527
+ # transform header-data to jkf
498
528
  def transform_root_header_data(ret)
499
529
  if ret["header"]["手番"]
500
530
  ret["initial"]["data"]["color"] = "下先".include?(ret["header"]["手番"]) ? 0 : 1
@@ -511,6 +541,7 @@ module Jkf::Parser
511
541
  end
512
542
  end
513
543
 
544
+ # transfrom forks to jkf
514
545
  def transform_root_forks(forks, moves)
515
546
  fork_stack = [{ "te" => 0, "moves" => moves }]
516
547
  forks.each do |f|
@@ -525,6 +556,7 @@ module Jkf::Parser
525
556
  end
526
557
  end
527
558
 
559
+ # transform initialboard to jkf
528
560
  def transform_initialboard(lines)
529
561
  board = []
530
562
  9.times do |i|
@@ -537,14 +569,17 @@ module Jkf::Parser
537
569
  { "preset" => "OTHER", "data" => { "board" => board } }
538
570
  end
539
571
 
572
+ # zenkaku number to number
540
573
  def zen2n(s)
541
574
  "0123456789".index(s)
542
575
  end
543
576
 
577
+ # kanji number to number (1)
544
578
  def kan2n(s)
545
579
  "〇一二三四五六七八九".index(s)
546
580
  end
547
581
 
582
+ # kanji number to number (2)
548
583
  def kan2n2(s)
549
584
  case s.length
550
585
  when 1
@@ -556,6 +591,7 @@ module Jkf::Parser
556
591
  end
557
592
  end
558
593
 
594
+ # kanji piece-type to csa
559
595
  def kind2csa(kind)
560
596
  if kind[0] == "成"
561
597
  {
@@ -585,6 +621,7 @@ module Jkf::Parser
585
621
  end
586
622
  end
587
623
 
624
+ # preset string to jkf
588
625
  def preset2str(preset)
589
626
  {
590
627
  "平手" => "HIRATE",
@@ -1,3 +1,4 @@
1
1
  module Jkf
2
- VERSION = "0.4.1".freeze
2
+ # Gem version
3
+ VERSION = "0.4.2".freeze
3
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jkf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - iyuuya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-24 00:00:00.000000000 Z
11
+ date: 2016-02-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: converter/parser of records of shogi
14
14
  email:
@@ -27,6 +27,7 @@ files:
27
27
  - Gemfile
28
28
  - Guardfile
29
29
  - LICENSE.txt
30
+ - README.en.md
30
31
  - README.md
31
32
  - Rakefile
32
33
  - bin/console