pgn_parser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/11.pgn +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +1 -0
- data/lib/pgn_parser.rb +294 -0
- data/lib/pgn_parser/version.rb +3 -0
- data/pgn_parser.gemspec +23 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 901aa0e18bad4ee0e401dae4106dd7acb6bf0c27
|
4
|
+
data.tar.gz: 850dd2f3e77f87983bab5cb3ea456492fc46d9f6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: acbf926115041dcca8a14ec17cdccf38b866a40a1224df5b0210dc9e13e224fab859449234b8a32e4a60d2e09c2cdc1c57986c925eab643835577e88469e046b
|
7
|
+
data.tar.gz: f10e87e9eadb25a1049a2402a463565c92a48a8093734702d71e4c5c27b9618aa2761b146817f2d195cdd1ef5d4141bb259a3919739d2e0b649e78f19badce1c
|
data/.gitignore
ADDED
data/11.pgn
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
[Event "Eurotel Trophy"]
|
2
|
+
[Site "Prague CZE"]
|
3
|
+
[Date "2002.04.30"]
|
4
|
+
[Round "2.1"]
|
5
|
+
[White "Polgar, Judit"]
|
6
|
+
[Black "Kasparov, Garri"]
|
7
|
+
[Result "0-1"]
|
8
|
+
[ECO "B33"]
|
9
|
+
[WhiteElo "2677"]
|
10
|
+
[BlackElo "2838"]
|
11
|
+
[EventDate "2002.04.28"]
|
12
|
+
[Annotator "Hathaway, Mark"]
|
13
|
+
|
14
|
+
1. e4 c5 2. Nf3 Nc6 { In some cases this restrains Pe4 sufficient to allow ...Ng8-f6, but in some other cases Black needs more control of e5. } ( 2...d6 ) 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 { Now Black has to decide how to prevent Nxc6 and e4-e5. To that end Black has played ...d6 (Scheveningen) , ...e5 (Sveshnikov) and ...Qb6 (Benko) . All have good qualities. } 5...e5 6. Ndb5 { If White doesn't try to exploit the weakness at d6 then his pieces become too passive. } 6...d6 7. Bg5 a6 8. Na3 b5 { threatening ...b4 and preventing Na3-c4-e3 } 9. Bxf6 ( 9. Nd5 ) 9...gxf6 { It seems odd that Black would allow such a pawn structure, but he can't easily be prevented from ...f6-f5xe4 to give him an advantage in central pawns. That the position has many weaknesses gives White room to develop and fight for a win. } 10. Nd5 Bg7 11. c3 f5 12. Bd3 ( 12. exf5 Bxf5 13. Qf3 Be6 ) ( 12. Nc2 $6 fxe4 { and Nc2 doesn't exactly fit into any part of the board. With Black ready to play ...f5 the king-side is safe and Nd5 occupies the most useful central square, so that leaves b4. But, moving Nc2-b4 doesn't serve much purpose at this point; only after a2-a4 softens up the queen-side would Nc2-b4 possibly become useful. } ) 12...Ne7 { After Ne7 it appears Black might prefer ...Bc8-b7, as is played in many Sicilian Defense games, to cut through the center of the board and to aim at Pg2, where White's king might soon reside. } ( 12...Be6 ) 13. Nxe7 Qxe7 14. O-O ( 14. exf5 { is consistent with the threat established by Bf1-d3, but it's unclear whether White can hold the pawn because of Black's mobile central pawns and generally good piece } 14...d5 ( 14...e4 $2 15. Bc2 Bxf5 $4 ( 15...O-O ) 16. Qd5 ) 15. Qh5 ) 14...O-O 15. Nc2 { Seeing that the piece needed to be improved and that d5 would be a good spot for it, she moves it now. } 15...f4 { It might be a little unusual to use this move when Bg7 blocks the g-file, but Kasparov has played the King's Indian Defense many times and understands how to handle the weak d5 and the open g-file. In this case he might not aim directly for an attack on Pg2 and Kg1. Instead he might just be preventing Ne3 or exf5, so he can return to ...Bc8-b7 with either ...f5 or ...d5 soon to follow. Kasparov is very much about achieving good overall piece activity. } 16. a4 bxa4 17. Rxa4 Qg5 { threatening ...Bh3 to checkmate with ...Qxg2# or to force g2-g3, so ...Bh3xf1 will win material and continue to weaken Kg1 } 18. f3 Bf6 19. Bc4 Kh8 { These moves are very much taken from a King's Indian Defense player's repertoire. } 20. Rf2 $2 ( 20. Qd2 Rg8 21. Rfa1 { coordinates the pieces a little better. Rf2 isn't good. } ) 20...Be7 21. Nb4 d5 $5 { Kasparov is always on the lookout for tactical shots which he can use to win or confuse the opponent. } 22. Bxd5 Bc5 { offering Ra8 is just the sort of audacious thing Kasparov is noted for. But, don't think it's just a bluff. He's calculated variations to determine if his compensation is sufficient. } 23. Bxa8 Rg8 24. Kf1 ( { I'm not quite sure what Kasparov had in mind after the obvious defensive move. } 24. Qf1 Bh3 25. Kh1 Bxf2 26. Qxf2 Bxg2+ 27. Kg1 Bh3+ 28. Kh1 Qd8 ( 28...Rxa8 29. Rxa6 Rd8 ( 29...Qd8 30. Rxa8 Qxa8 31. Qg1 f5 ) 30. Nd5 ) 29. Bd5 ) 24...Bxf2 25. Ke2 ( 25. Kxf2 Qxg2+ 26. Ke1 Qxb2 { and the threat of ...Rg1# is very strong } ) 25...Qxg2 26. Kd3 { Material is nominally equal, but the exposed Kd3 could be a problem. } 26...Be3 27. Bd5 Qxh2 28. Kc4 Rg1 29. Qd3 Bh3 { It's odd to see all these Black pieces cramped into the corner, but Black threatens ...Bf1 to win a queen! } 30. Kb3 Bf1 31. Qc2 Qxc2+ { It's a little surprising, after what had gone before, to see simplification; Black has a passed Ph7 and wants to advance it, so the h-file had to be cleared. } ( 31...Rg2 32. Qb1 Bb5 33. Ra5 { and White is somewhat coordinated and threatening Nxa6 to gain more space } ) 32. Kxc2 Kg7 33. c4 Be2 { I suppose he's decided he can't just run Ph7 forward because Pc4 is also in good shape to advance and White's pieces might suddenly swarm Kg7. So, he has to continue the fight and await further simplifications when his king will be safer, then the pawns can advance. } 34. Rxa6 Bd1+ { prevents White's king from running to a2 (via b3) to get away from checks } ( 34...Rc1+ 35. Kb3 Bd1+ 36. Ka2 ) 35. Kd3 Bxf3 36. Nc6 Rd1+ 37. Kc3 Bg4 { clearing the way for ...f4-f3 and perhaps teasing Polgar into Nxe5?? Maybe Black has a won position anyway. White's pawns can't advance yet and with Be3 preventing Ra6-a7 there's no attack on Kg7. This is the moment for pawn advances. } 38. Nxe5 $4 Bd4+ 39. Kc2 Bxe5 $19 40. Ra7 Re1 41. Rxf7+ Kg6 42. c5 Re2+ 43. Kc1 f3 44. Bc4 ( 44. b4 Rxe4 ) 44...Rxe4 45. Bd5 Rf4
|
15
|
+
0-1
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Joseph Emmanuel Dayo
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# PgnParser
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'pgn_parser'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install pgn_parser
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Pretty straightforward.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'pgn_parser'
|
25
|
+
require 'json'
|
26
|
+
|
27
|
+
@pgn_data = File.read(File.join(File.dirname(__FILE__),'11.pgn'))
|
28
|
+
|
29
|
+
pgn = PGN::Parser.new(@pgn_data)
|
30
|
+
|
31
|
+
puts pgn.parse.to_json
|
32
|
+
```
|
33
|
+
|
34
|
+
## Contributing
|
35
|
+
|
36
|
+
1. Fork it ( http://github.com/<my-github-username>/pgn_parser/fork )
|
37
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
38
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
39
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
40
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/pgn_parser.rb
ADDED
@@ -0,0 +1,294 @@
|
|
1
|
+
require "pgn_parser/version"
|
2
|
+
|
3
|
+
module PGN
|
4
|
+
class Parser
|
5
|
+
|
6
|
+
def initialize(pgn_content)
|
7
|
+
@pgn_content = pgn_content
|
8
|
+
@headers = []
|
9
|
+
@movelist = []
|
10
|
+
@game_attributes = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def headers
|
14
|
+
@headers
|
15
|
+
end
|
16
|
+
|
17
|
+
def attributes
|
18
|
+
@game_attributes
|
19
|
+
end
|
20
|
+
|
21
|
+
def movelist
|
22
|
+
@movelist
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse
|
26
|
+
current_index = 0
|
27
|
+
state = :initial
|
28
|
+
buffer = ''
|
29
|
+
while (current_index < @pgn_content.size)
|
30
|
+
current_char = @pgn_content[current_index]
|
31
|
+
current_index+=1
|
32
|
+
if state==:initial
|
33
|
+
if current_char=='['
|
34
|
+
state = :start_parse_header
|
35
|
+
next
|
36
|
+
elsif (current_char == ' ' || current_char == "\n" || current_char == "\r")
|
37
|
+
next
|
38
|
+
else
|
39
|
+
break
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if state==:start_parse_header
|
44
|
+
if current_char == ']'
|
45
|
+
state = :initial
|
46
|
+
hd = parse_header(buffer)
|
47
|
+
@headers << hd
|
48
|
+
@game_attributes[hd[:type]] = hd[:value]
|
49
|
+
buffer = ''
|
50
|
+
next
|
51
|
+
else
|
52
|
+
buffer << current_char
|
53
|
+
next
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
@movelist = parse_moves(@pgn_content,current_index - 1)[0]
|
60
|
+
{moves: @movelist}.merge(@game_attributes)
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_moves(content, current_index, initial_state = :parse_moves)
|
64
|
+
state = initial_state
|
65
|
+
buffer = ''
|
66
|
+
state_before = nil
|
67
|
+
current_move = {}
|
68
|
+
current_alternative = {}
|
69
|
+
movelist = []
|
70
|
+
while (current_index < content.size)
|
71
|
+
current_char = content[current_index]
|
72
|
+
current_index+=1
|
73
|
+
if state == :parse_moves
|
74
|
+
if current_char == ' '
|
75
|
+
next
|
76
|
+
elsif current_char == '('
|
77
|
+
x = nil
|
78
|
+
x, current_index = parse_moves(content, current_index)
|
79
|
+
elsif current_char == ')'
|
80
|
+
current_index+=1
|
81
|
+
break
|
82
|
+
elsif current_char == '{'
|
83
|
+
state = :start_parse_comment_section_paren
|
84
|
+
next
|
85
|
+
elsif current_char >= '0' && current_char <= '9'
|
86
|
+
state =:parse_move_text_number
|
87
|
+
buffer << current_char
|
88
|
+
next
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if state == :parse_move_text_number
|
93
|
+
if current_char == '.'
|
94
|
+
current_move[:num] = buffer.to_i
|
95
|
+
buffer = ''
|
96
|
+
state = :parse_move_first_position
|
97
|
+
next
|
98
|
+
else
|
99
|
+
buffer << current_char
|
100
|
+
next
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if state == :parse_move_first_position
|
105
|
+
if (current_char == ' ')
|
106
|
+
next
|
107
|
+
elsif (current_char == '.')
|
108
|
+
state = :continuation_indicator
|
109
|
+
current_move[:cont] = true
|
110
|
+
next
|
111
|
+
else
|
112
|
+
buffer << current_char
|
113
|
+
state = :begin_parse_move_first_position
|
114
|
+
next
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if state == :continuation_indicator
|
119
|
+
if (current_char == '.' )
|
120
|
+
next
|
121
|
+
elsif (current_char == ' ')
|
122
|
+
state = :parse_move_second_position
|
123
|
+
next
|
124
|
+
else
|
125
|
+
buffer << current_char
|
126
|
+
state = :parse_move_second_position
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if state == :begin_parse_move_first_position
|
131
|
+
if (current_char == ' ')
|
132
|
+
current_move[:w] = buffer
|
133
|
+
buffer = ''
|
134
|
+
state = :parse_move_second_position
|
135
|
+
next
|
136
|
+
elsif (current_char == "\n")
|
137
|
+
break
|
138
|
+
else
|
139
|
+
buffer << current_char
|
140
|
+
next
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
if state == :parse_move_second_position
|
145
|
+
if (current_char == ' ')
|
146
|
+
next
|
147
|
+
elsif (current_char == ')')
|
148
|
+
current_index+=1
|
149
|
+
break
|
150
|
+
elsif (current_char == '$')
|
151
|
+
buf = ''
|
152
|
+
while (content[current_index] >='0') && (content[current_index]<='9') && (current_index < content.size)
|
153
|
+
buf << content[current_index]
|
154
|
+
current_index+=1
|
155
|
+
end
|
156
|
+
current_move[:w_nag] = buf
|
157
|
+
next
|
158
|
+
elsif (current_char == '{')
|
159
|
+
state = :start_parse_comment_section_paren
|
160
|
+
next
|
161
|
+
elsif (current_char == '(')
|
162
|
+
current_move[:w_alt] = [] if current_move[:w_alt].nil?
|
163
|
+
alternate, current_index = parse_moves(content, current_index + 1)
|
164
|
+
current_move[:w_alt] << alternate
|
165
|
+
next
|
166
|
+
elsif (current_char >= '0' && current_char <= '9')
|
167
|
+
buffer = ''
|
168
|
+
movelist << current_move.dup
|
169
|
+
current_move = {}
|
170
|
+
buffer << current_char
|
171
|
+
state = :parse_move_text_number
|
172
|
+
else
|
173
|
+
buffer << current_char
|
174
|
+
state = :begin_parse_move_second_position
|
175
|
+
next
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
if state == :begin_parse_move_second_position
|
180
|
+
if (current_char == ' ')
|
181
|
+
current_move[:b] = buffer
|
182
|
+
buffer = ''
|
183
|
+
state = :start_comment_section
|
184
|
+
next
|
185
|
+
elsif (current_char == "\n")
|
186
|
+
current_move[:b] = buffer
|
187
|
+
movelist << current_move.dup
|
188
|
+
break
|
189
|
+
else
|
190
|
+
buffer << current_char
|
191
|
+
next
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
if state == :start_comment_section
|
196
|
+
if (current_char == ' ')
|
197
|
+
next
|
198
|
+
elsif (current_char == '$')
|
199
|
+
buf = ''
|
200
|
+
while (content[current_index] >='0') && (content[current_index]<='9') && (current_index < content.size)
|
201
|
+
buf << content[current_index]
|
202
|
+
current_index+=1
|
203
|
+
end
|
204
|
+
current_move[:b_nag] = buf
|
205
|
+
next
|
206
|
+
elsif (current_char == '{')
|
207
|
+
state = :start_parse_comment_section_paren
|
208
|
+
next
|
209
|
+
elsif (current_char == ')')
|
210
|
+
current_index+=1
|
211
|
+
break
|
212
|
+
elsif (current_char == '(')
|
213
|
+
current_move[:b_alt] = [] if current_move[:b_alt].nil?
|
214
|
+
alternate, current_index = parse_moves(content, current_index)
|
215
|
+
current_move[:b_alt] << alternate
|
216
|
+
next
|
217
|
+
elsif current_char >= '0' && current_char <= '9'
|
218
|
+
buffer = ''
|
219
|
+
movelist << current_move.dup
|
220
|
+
current_move = {}
|
221
|
+
buffer << current_char
|
222
|
+
state =:parse_move_text_number
|
223
|
+
next
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
if state == :start_parse_comment_section_paren
|
228
|
+
if (current_char == '}')
|
229
|
+
current_move[:comment] = buffer.dup
|
230
|
+
buffer = ''
|
231
|
+
movelist << current_move.dup
|
232
|
+
current_move = {}
|
233
|
+
state = :parse_moves
|
234
|
+
next
|
235
|
+
else
|
236
|
+
buffer << current_char
|
237
|
+
next
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
if state == :start_comment_section
|
243
|
+
movelist << current_move.dup
|
244
|
+
elsif state == :begin_parse_move_first_position
|
245
|
+
current_move[:w] = buffer
|
246
|
+
movelist << current_move.dup
|
247
|
+
elsif state == :start_parse_comment_section
|
248
|
+
movelist << current_move.dup
|
249
|
+
elsif state == :parse_move_second_position
|
250
|
+
movelist << current_move.dup
|
251
|
+
end
|
252
|
+
[movelist, current_index]
|
253
|
+
end
|
254
|
+
|
255
|
+
def parse_header(header)
|
256
|
+
event_type = ""
|
257
|
+
event_value = ""
|
258
|
+
state = :parse_type
|
259
|
+
current_index = 0
|
260
|
+
buffer = ''
|
261
|
+
while (current_index < header.size)
|
262
|
+
current_char = header[current_index]
|
263
|
+
current_index+=1
|
264
|
+
if state==:parse_type
|
265
|
+
if current_char == ' '
|
266
|
+
event_type = buffer.dup
|
267
|
+
buffer = ''
|
268
|
+
state=:start_parse_value
|
269
|
+
next
|
270
|
+
else
|
271
|
+
buffer << current_char
|
272
|
+
next
|
273
|
+
end
|
274
|
+
elsif state==:start_parse_value
|
275
|
+
if current_char=='"'
|
276
|
+
state=:parse_value
|
277
|
+
next
|
278
|
+
else
|
279
|
+
next
|
280
|
+
end
|
281
|
+
elsif state==:parse_value
|
282
|
+
if current_char=='"'
|
283
|
+
event_value = buffer.dup
|
284
|
+
buffer = ''
|
285
|
+
else
|
286
|
+
buffer << current_char
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
end
|
291
|
+
{type: event_type, value: event_value}
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
data/pgn_parser.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pgn_parser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pgn_parser"
|
8
|
+
spec.version = PgnParser::VERSION
|
9
|
+
spec.authors = ["Joseph Emmanuel Dayo"]
|
10
|
+
spec.email = ["joseph.dayo@gmail.com"]
|
11
|
+
spec.summary = %q{A pure ruby parser for chess pgn files.}
|
12
|
+
spec.description = %q{A pure ruby parser for chess pgn files. Read pgn files an allow for a format easily readable for chess computers}
|
13
|
+
spec.homepage = "https://github.com/jedld/chess_pgn_parser.git"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pgn_parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joseph Emmanuel Dayo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A pure ruby parser for chess pgn files. Read pgn files an allow for a
|
42
|
+
format easily readable for chess computers
|
43
|
+
email:
|
44
|
+
- joseph.dayo@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- 11.pgn
|
51
|
+
- Gemfile
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- lib/pgn_parser.rb
|
56
|
+
- lib/pgn_parser/version.rb
|
57
|
+
- pgn_parser.gemspec
|
58
|
+
homepage: https://github.com/jedld/chess_pgn_parser.git
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.2.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: A pure ruby parser for chess pgn files.
|
82
|
+
test_files: []
|
83
|
+
has_rdoc:
|