spells 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b094afd2a13a91478d702cd86dac1ea10602459
4
+ data.tar.gz: 0aac6a32f783fb79646ee7a895fa598e1d266cbe
5
+ SHA512:
6
+ metadata.gz: 834db832ac354959347a05a656ca92cb98b89f41fa6e24c93f7023c330327f6ba9a8b61120b70417ca3bd92b676764c0cb52ecdf2e3ec82183332043389b1e0c
7
+ data.tar.gz: 7e1ad9cc05a1ce606266305bd2f1fe2e85f6632bd0fcc521f5d15ec77dab2a9dd92897dfd6285995660b1349d1cef4e671bba16e916a0110d19a8e16d996cd70
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1 @@
1
+ spells
@@ -0,0 +1,2 @@
1
+ 2.1.0
2
+
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spells.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Eric Cohen
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.
@@ -0,0 +1,29 @@
1
+ # Spells
2
+
3
+ Spells is a library for parsing the text on Magic the Gathering cards
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'spells'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install spells
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/spells/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,21 @@
1
+ ---
2
+ - !ruby/object:Spells::Card
3
+ name: Nezumi Bone-Reader
4
+ text: |-
5
+ {B}, Sacrifice a creature: Target player discards a card. Activate this ability only any time you could cast a sorcery.
6
+
7
+ - !ruby/object:Spells::Card
8
+ name: Squallmonger
9
+ text: |-
10
+ {2}: Squallmonger deals 1 damage to each creature with flying and each player. Any player may activate this ability.
11
+
12
+ - !ruby/object:Spells::Card
13
+ name: Ghost-Lit Raider
14
+ text: |-
15
+ {2}{R}, {T}: Ghost-Lit Raider deals 2 damage to target creature.
16
+ Channel - {3}{R}, Discard Ghost-Lit Raider: Ghost-Lit Raider deals 4 damage to target creature.
17
+
18
+ - !ruby/object:Spells::Card
19
+ name: Abomination
20
+ text: |-
21
+ Whenever Abomination blocks or becomes blocked by a green or white creature, destroy that creature at end of combat.
@@ -0,0 +1,56 @@
1
+ grammar Spells
2
+ include Spells::Punctuation
3
+ include Spells::Symbols
4
+
5
+ rule card_text
6
+ ability ( new_line ability )* <ParseNode>
7
+ end
8
+
9
+ rule ability
10
+ triggered_ability / activated_ability
11
+ end
12
+
13
+ rule triggered_ability
14
+ 'Whenever' space words comma space effect <TriggeredAbility>
15
+ end
16
+
17
+ rule activated_ability
18
+ ( ability_word space dash space )? cost colon space effect <ActivatedAbility>
19
+ end
20
+
21
+ rule ability_word
22
+ 'Channel' / 'Battalion'
23
+ end
24
+
25
+ rule cost
26
+ cost_part ( comma space cost_part )*
27
+ end
28
+
29
+ rule cost_part
30
+ mana_cost / tap_symbol / text_cost
31
+ end
32
+
33
+ rule mana_cost
34
+ mana_symbol+
35
+ end
36
+
37
+ rule tap_cost
38
+ tap_symbol
39
+ end
40
+
41
+ rule text_cost
42
+ words
43
+ end
44
+
45
+ rule effect
46
+ words dot ( space words dot )*
47
+ end
48
+
49
+ rule words
50
+ word ( space word )*
51
+ end
52
+
53
+ rule word
54
+ [A-Za-z1-9\-]+
55
+ end
56
+ end
@@ -0,0 +1,35 @@
1
+ module Spells
2
+ grammar Punctuation
3
+ rule new_line
4
+ "\n"
5
+ end
6
+
7
+ rule comma
8
+ ','
9
+ end
10
+
11
+ rule colon
12
+ ':'
13
+ end
14
+
15
+ rule space
16
+ ' '
17
+ end
18
+
19
+ rule dot
20
+ '.'
21
+ end
22
+
23
+ rule opening_brace
24
+ '{'
25
+ end
26
+
27
+ rule closing_brace
28
+ '}'
29
+ end
30
+
31
+ rule dash
32
+ '-'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ module Spells
2
+ grammar Symbols
3
+ include Punctuation
4
+
5
+ rule tap_symbol
6
+ opening_brace 'T' closing_brace
7
+ end
8
+
9
+ rule mana_symbol
10
+ mana_symbol_white /
11
+ mana_symbol_blue /
12
+ mana_symbol_black /
13
+ mana_symbol_red /
14
+ mana_symbol_green /
15
+ mana_symbol_colorless
16
+ end
17
+
18
+ rule mana_symbol_white
19
+ opening_brace 'W' closing_brace
20
+ end
21
+
22
+ rule mana_symbol_blue
23
+ opening_brace 'U' closing_brace
24
+ end
25
+
26
+ rule mana_symbol_black
27
+ opening_brace 'B' closing_brace
28
+ end
29
+
30
+ rule mana_symbol_red
31
+ opening_brace 'R' closing_brace
32
+ end
33
+
34
+ rule mana_symbol_green
35
+ opening_brace 'G' closing_brace
36
+ end
37
+
38
+ rule mana_symbol_colorless
39
+ opening_brace [1-9]+ closing_brace
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ require 'treetop'
2
+ require 'singleton'
3
+
4
+ require "spells/version"
5
+
6
+ module Spells
7
+ autoload :Parser, 'spells/parser'
8
+ autoload :ParseNode, 'spells/parse_node'
9
+
10
+ autoload :Card, 'spells/card'
11
+ autoload :Ability, 'spells/ability'
12
+ autoload :ActivatedAbility, 'spells/activated_ability'
13
+ autoload :TriggeredAbility, 'spells/triggered_ability'
14
+ end
@@ -0,0 +1,4 @@
1
+ module Spells
2
+ class Ability < ParseNode
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Spells
2
+ class ActivatedAbility < Ability
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ module Spells
2
+ class Card
3
+ attr_accessor :name
4
+ attr_accessor :text
5
+
6
+ def abilities
7
+ parsed_text.nodes_of Ability
8
+ end
9
+
10
+ def triggered_abilities
11
+ parsed_text.nodes_of TriggeredAbility
12
+ end
13
+
14
+ def activated_abilities
15
+ parsed_text.nodes_of ActivatedAbility
16
+ end
17
+
18
+ protected
19
+
20
+ def parsed_text
21
+ @parsed_text ||= Spells::Parser.instance.parse text
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ module Spells
2
+ class ParseNode < Treetop::Runtime::SyntaxNode
3
+ def nodes_of(klass)
4
+ ParseNode.nodes_of klass, self
5
+ end
6
+
7
+ def self.nodes_of(klass, tree)
8
+ return if tree.elements.nil?
9
+
10
+ tree.
11
+ elements.
12
+ map { |element| element.kind_of?(klass) ? element : nodes_of(klass, element) }.
13
+ flatten.
14
+ compact
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Spells
2
+ class Parser
3
+ include ::Singleton
4
+
5
+ def initialize
6
+ Treetop.load File.expand_path('../../../grammar/spells/punctuation.treetop', __FILE__)
7
+ Treetop.load File.expand_path('../../../grammar/spells/symbols.treetop', __FILE__)
8
+ Treetop.load File.expand_path('../../../grammar/spells.treetop', __FILE__)
9
+ @parser = SpellsParser.new
10
+ end
11
+
12
+ def parse(text)
13
+ @parser.parse text
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module Spells
2
+ class TriggeredAbility < Ability
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Spells
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'spells'
3
+
4
+ require 'yaml'
5
+
6
+ def card_fixtures
7
+ @cards ||= YAML.load_file File.expand_path('../../fixtures/cards.yml', __FILE__)
8
+ end
9
+
10
+ def card_fixture(name)
11
+ card_fixtures.find { |card| card.name == name }
12
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spells::Card do
4
+
5
+ context '#abilities' do
6
+ it 'successfully parses abilities for all fixtures' do
7
+ card_fixtures.each do |card|
8
+ expect(card.abilities).not_to eq(nil)
9
+ expect(card.abilities).to be_an(Array)
10
+ end
11
+ end
12
+
13
+ it 'correctly parses abilities for "Nezumi Bone-Reader"' do
14
+ expect(card_fixture('Nezumi Bone-Reader').abilities.map { |ability| ability.text_value }).
15
+ to eq([
16
+ '{B}, Sacrifice a creature: Target player discards a card. Activate this ability only any time you could cast a sorcery.'
17
+ ])
18
+ end
19
+
20
+ it 'correctly parses abilities for "Squallmonger"' do
21
+ expect(card_fixture('Squallmonger').abilities.map { |ability| ability.text_value }).
22
+ to eq([
23
+ '{2}: Squallmonger deals 1 damage to each creature with flying and each player. Any player may activate this ability.'
24
+ ])
25
+ end
26
+
27
+ it 'correctly parses abilities for "Ghost-Lit Raider"' do
28
+ expect(card_fixture('Ghost-Lit Raider').abilities.map { |ability| ability.text_value }).
29
+ to eq([
30
+ '{2}{R}, {T}: Ghost-Lit Raider deals 2 damage to target creature.',
31
+ 'Channel - {3}{R}, Discard Ghost-Lit Raider: Ghost-Lit Raider deals 4 damage to target creature.'
32
+ ])
33
+ end
34
+
35
+ it 'correctly parses abilities for "Abomination"' do
36
+ expect(card_fixture('Abomination').abilities.map { |ability| ability.text_value }).
37
+ to eq([
38
+ 'Whenever Abomination blocks or becomes blocked by a green or white creature, destroy that creature at end of combat.'
39
+ ])
40
+ end
41
+ end
42
+
43
+ context '#activated_abilities' do
44
+ it 'successfully parses activated abilities for all fixtures' do
45
+ card_fixtures.each do |card|
46
+ expect(card.activated_abilities).not_to eq(nil)
47
+ expect(card.activated_abilities).to be_an(Array)
48
+ end
49
+ end
50
+
51
+ it 'correctly parses activated abilities for "Nezumi Bone-Reader"' do
52
+ expect(card_fixture('Nezumi Bone-Reader').activated_abilities.map { |ability| ability.text_value }).
53
+ to eq([
54
+ '{B}, Sacrifice a creature: Target player discards a card. Activate this ability only any time you could cast a sorcery.'
55
+ ])
56
+ end
57
+
58
+ it 'correctly parses activated abilities for "Squallmonger"' do
59
+ expect(card_fixture('Squallmonger').activated_abilities.map { |ability| ability.text_value }).
60
+ to eq([
61
+ '{2}: Squallmonger deals 1 damage to each creature with flying and each player. Any player may activate this ability.'
62
+ ])
63
+ end
64
+
65
+ it 'correctly parses activated abilities for "Ghost-Lit Raider"' do
66
+ expect(card_fixture('Ghost-Lit Raider').activated_abilities.map { |ability| ability.text_value }).
67
+ to eq([
68
+ '{2}{R}, {T}: Ghost-Lit Raider deals 2 damage to target creature.',
69
+ 'Channel - {3}{R}, Discard Ghost-Lit Raider: Ghost-Lit Raider deals 4 damage to target creature.'
70
+ ])
71
+ end
72
+
73
+ it 'correctly parses activated abilities for "Abomination"' do
74
+ expect(card_fixture('Abomination').activated_abilities.map { |ability| ability.text_value }).
75
+ to eq([])
76
+ end
77
+ end
78
+
79
+ context '#triggered_abilities' do
80
+ it 'successfully parses triggered abilities for all fixtures' do
81
+ card_fixtures.each do |card|
82
+ expect(card.triggered_abilities).not_to eq(nil)
83
+ expect(card.triggered_abilities).to be_an(Array)
84
+ end
85
+ end
86
+
87
+ it 'correctly parses triggered abilities for "Nezumi Bone-Reader"' do
88
+ expect(card_fixture('Nezumi Bone-Reader').triggered_abilities.map { |ability| ability.text_value }).
89
+ to eq([])
90
+ end
91
+
92
+ it 'correctly parses triggered abilities for "Ghost-Lit Raider"' do
93
+ expect(card_fixture('Ghost-Lit Raider').triggered_abilities.map { |ability| ability.text_value }).
94
+ to eq([])
95
+ end
96
+
97
+ it 'correctly parses triggered abilities for "Ghost-Lit Raider"' do
98
+ expect(card_fixture('Ghost-Lit Raider').triggered_abilities.map { |ability| ability.text_value }).
99
+ to eq([])
100
+ end
101
+
102
+ it 'correctly parses triggered abilities for "Abomination"' do
103
+ expect(card_fixture('Abomination').triggered_abilities.map { |ability| ability.text_value }).
104
+ to eq([
105
+ 'Whenever Abomination blocks or becomes blocked by a green or white creature, destroy that creature at end of combat.'
106
+ ])
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spells::Parser do
4
+ describe '#parse' do
5
+ card_fixtures.each do |card|
6
+ it "successfully parses fixture card '#{card.name}'" do
7
+ expect(Spells::Parser.instance.parse(card.text)).not_to eq(nil)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spells do
4
+ it 'has a version number' do
5
+ expect(Spells::VERSION).not_to be nil
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'spells/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'spells'
8
+ spec.version = Spells::VERSION
9
+ spec.authors = ['Eric Cohen']
10
+ spec.email = ['eirc.eirc@gmail.com']
11
+ spec.summary = %q{Spells is a library for parsing the text on Magic the Gathering cards}
12
+ spec.homepage = 'http://github.com/eirc/spells'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rspec'
23
+
24
+ spec.add_runtime_dependency 'treetop'
25
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spells
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric Cohen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-03 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.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
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
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: treetop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - eirc.eirc@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".ruby-gemset"
79
+ - ".ruby-version"
80
+ - ".travis.yml"
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - fixtures/cards.yml
86
+ - grammar/spells.treetop
87
+ - grammar/spells/punctuation.treetop
88
+ - grammar/spells/symbols.treetop
89
+ - lib/spells.rb
90
+ - lib/spells/ability.rb
91
+ - lib/spells/activated_ability.rb
92
+ - lib/spells/card.rb
93
+ - lib/spells/parse_node.rb
94
+ - lib/spells/parser.rb
95
+ - lib/spells/triggered_ability.rb
96
+ - lib/spells/version.rb
97
+ - spec/spec_helper.rb
98
+ - spec/spells/card_spec.rb
99
+ - spec/spells/parser_spec.rb
100
+ - spec/spells_spec.rb
101
+ - spells.gemspec
102
+ homepage: http://github.com/eirc/spells
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.2.2
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Spells is a library for parsing the text on Magic the Gathering cards
126
+ test_files:
127
+ - spec/spec_helper.rb
128
+ - spec/spells/card_spec.rb
129
+ - spec/spells/parser_spec.rb
130
+ - spec/spells_spec.rb