jkf 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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