armory 0.1.0
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.
- data/LICENSE +20 -0
- data/README.rdoc +25 -0
- data/lib/armory.rb +89 -0
- data/lib/armory/character.rb +82 -0
- data/lib/armory/guild.rb +53 -0
- data/lib/armory/version.rb +3 -0
- data/spec/armory_spec.rb +87 -0
- data/spec/character_spec.rb +69 -0
- data/spec/fixtures/guild.xml +19 -0
- data/spec/fixtures/hunter.xml +159 -0
- data/spec/spec_helper.rb +18 -0
- metadata +141 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Chris Gaffney
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= Armory
|
2
|
+
|
3
|
+
Library for downloading and parsing the wow armory
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
$ gem install armory
|
8
|
+
|
9
|
+
== Note on Patches/Pull Requests
|
10
|
+
|
11
|
+
* Fork the project.
|
12
|
+
* Make your feature addition or bug fix.
|
13
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
14
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
|
15
|
+
* Send me a pull request. Bonus points for topic branches.
|
16
|
+
|
17
|
+
== Development
|
18
|
+
|
19
|
+
$ gem install bundler (if you don't have it)
|
20
|
+
$ bundle install
|
21
|
+
$ bundle exec rake
|
22
|
+
|
23
|
+
== Copyright
|
24
|
+
|
25
|
+
See LICENSE for details.
|
data/lib/armory.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
module Armory
|
5
|
+
extend self
|
6
|
+
|
7
|
+
autoload :VERSION, "armory/version"
|
8
|
+
|
9
|
+
autoload :Guild, "armory/guild"
|
10
|
+
autoload :Character, "armory/character"
|
11
|
+
|
12
|
+
USER_AGENT = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.4) Gecko/20100503 Firefox/3.6.4'
|
13
|
+
|
14
|
+
class Error < Exception; end
|
15
|
+
class CharacterNotFound < Error; end
|
16
|
+
class GuildNotFound < Error; end
|
17
|
+
|
18
|
+
Factions = {
|
19
|
+
0 => "Alliance",
|
20
|
+
1 => "Horde"
|
21
|
+
}
|
22
|
+
|
23
|
+
Genders = {
|
24
|
+
0 => "Male",
|
25
|
+
1 => "Female"
|
26
|
+
}
|
27
|
+
|
28
|
+
Races = {
|
29
|
+
1 => "Human",
|
30
|
+
2 => "Orc",
|
31
|
+
3 => "Dwarf",
|
32
|
+
4 => "Night Elf",
|
33
|
+
5 => "Undead",
|
34
|
+
6 => "Tauren",
|
35
|
+
7 => "Gnome",
|
36
|
+
8 => "Troll",
|
37
|
+
10 => "Blood Elf",
|
38
|
+
11 => "Draenei"
|
39
|
+
}
|
40
|
+
|
41
|
+
Classes = {
|
42
|
+
1 => "Warrior",
|
43
|
+
2 => "Paladin",
|
44
|
+
3 => "Hunter",
|
45
|
+
4 => "Rogue",
|
46
|
+
5 => "Priest",
|
47
|
+
6 => "Death Knight",
|
48
|
+
7 => "Shaman",
|
49
|
+
8 => "Mage",
|
50
|
+
9 => "Warlock",
|
51
|
+
11 => "Druid"
|
52
|
+
}
|
53
|
+
|
54
|
+
# TODO: Validate realms
|
55
|
+
# TODO: Handle different regions
|
56
|
+
# http://us.wowarmory.com/character-sheet.xml?r=Detheroc&n=Hunter
|
57
|
+
def character_sheet(region, realm, character)
|
58
|
+
response = make_request(region, 'character-sheet', :r => realm, :n => character)
|
59
|
+
|
60
|
+
case response.code
|
61
|
+
when 404
|
62
|
+
raise CharacterNotFound, "Could not find #{character} on #{region}:#{realm}"
|
63
|
+
end
|
64
|
+
|
65
|
+
Character.from_armory(Nokogiri::XML(response.body))
|
66
|
+
end
|
67
|
+
|
68
|
+
def guild_info(region, realm, guild_name)
|
69
|
+
response = make_request(region, 'guild-info', :r => realm, :gn => guild_name)
|
70
|
+
|
71
|
+
case response.code
|
72
|
+
when 404
|
73
|
+
raise GuildNotFound, "Could not find #{guild_name} on #{region}:#{realm}"
|
74
|
+
end
|
75
|
+
|
76
|
+
Guild.from_armory(Nokogiri::XML(response.body))
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# TODO: Use region
|
82
|
+
def make_request(region, page, params)
|
83
|
+
Typhoeus::Request.get("http://us.wowarmory.com/#{page}.xml", {
|
84
|
+
:user_agent => USER_AGENT,
|
85
|
+
:params => params
|
86
|
+
})
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Armory
|
4
|
+
class Character
|
5
|
+
|
6
|
+
attr_accessor :name, :level, :guild, :realm, :battle_group, :last_modified
|
7
|
+
attr_accessor :class_id, :gender_id, :race_id, :faction_id
|
8
|
+
attr_reader :items
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@items = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def class_name
|
15
|
+
Armory::Classes[class_id]
|
16
|
+
end
|
17
|
+
|
18
|
+
def gender
|
19
|
+
Armory::Genders[gender_id]
|
20
|
+
end
|
21
|
+
|
22
|
+
def race
|
23
|
+
Armory::Races[race_id]
|
24
|
+
end
|
25
|
+
|
26
|
+
def faction
|
27
|
+
Armory::Factions[faction_id]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.from_armory(doc)
|
31
|
+
Character.new.tap do |char|
|
32
|
+
info = doc.css("characterInfo character").first
|
33
|
+
|
34
|
+
char.name = info.attr("name")
|
35
|
+
char.level = info.attr("level").to_i
|
36
|
+
char.guild = info.attr("guildName")
|
37
|
+
char.realm = info.attr("realm")
|
38
|
+
char.battle_group = info.attr("battleGroup")
|
39
|
+
char.last_modified = Date.parse(info.attr('lastModified'))
|
40
|
+
|
41
|
+
# Attribute ids
|
42
|
+
char.race_id = info.attr("raceId").to_i
|
43
|
+
char.class_id = info.attr("classId").to_i
|
44
|
+
char.gender_id = info.attr("genderId").to_i
|
45
|
+
char.faction_id = info.attr("factionId").to_i
|
46
|
+
|
47
|
+
doc.css("characterTab items item").each do |item|
|
48
|
+
char.items << Item.from_armory(item)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Item
|
54
|
+
attr_accessor :id, :name, :level, :slot, :rarity
|
55
|
+
attr_accessor :durability, :max_durability, :enchant_id
|
56
|
+
attr_reader :gems
|
57
|
+
|
58
|
+
def initialize
|
59
|
+
@gems = []
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.from_armory(doc)
|
63
|
+
Item.new.tap do |item|
|
64
|
+
item.id = doc.attr('id').to_i
|
65
|
+
item.name = doc.attr('name')
|
66
|
+
item.level = doc.attr('level').to_i
|
67
|
+
item.slot = doc.attr('slot').to_i
|
68
|
+
item.rarity = doc.attr('rarity').to_i
|
69
|
+
|
70
|
+
item.durability = doc.attr('durability').to_i
|
71
|
+
item.max_durability = doc.attr('maxDurability').to_i
|
72
|
+
item.enchant_id = doc.attr('permanentEnchantItemId').to_i
|
73
|
+
|
74
|
+
3.times do |i|
|
75
|
+
gem = doc.attr("gem#{i}Id").to_i
|
76
|
+
item.gems << gem if gem != 0
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/armory/guild.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Armory
|
2
|
+
class Guild
|
3
|
+
attr_accessor :name, :realm, :faction_id, :characters
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@characters = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def faction
|
10
|
+
Armory::Factions[faction_id]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_armory(doc)
|
14
|
+
Guild.new.tap do |guild|
|
15
|
+
info = doc.css("guildInfo")
|
16
|
+
header = info.css("guildHeader")
|
17
|
+
|
18
|
+
guild.name = header.attr("name").value
|
19
|
+
guild.realm = header.attr("realm").value
|
20
|
+
guild.faction_id = header.attr("faction").value.to_i
|
21
|
+
|
22
|
+
info.css("guild members character").each do |member|
|
23
|
+
guild.characters << Armory::Guild::Character.new(
|
24
|
+
member.attr('name'),
|
25
|
+
member.attr('rank').to_i,
|
26
|
+
member.attr('level').to_i,
|
27
|
+
member.attr('classId').to_i,
|
28
|
+
member.attr('genderId').to_i,
|
29
|
+
member.attr('raceId').to_i
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Character < Struct.new(:name, :rank, :level, :class_id, :gender_id, :race_id)
|
36
|
+
def class_name
|
37
|
+
Armory::Classes[class_id]
|
38
|
+
end
|
39
|
+
|
40
|
+
def gender
|
41
|
+
Armory::Genders[gender_id]
|
42
|
+
end
|
43
|
+
|
44
|
+
def race
|
45
|
+
Armory::Races[race_id]
|
46
|
+
end
|
47
|
+
|
48
|
+
def faction
|
49
|
+
Armory::Factions[faction_id]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/armory_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Armory do
|
4
|
+
describe "#character_sheet" do
|
5
|
+
# TODO: Handle title
|
6
|
+
# TODO: Handle skills
|
7
|
+
# TODO: Handle equipment
|
8
|
+
it "should properly parse a character" do
|
9
|
+
response = stub(
|
10
|
+
:body => fixture("hunter"),
|
11
|
+
:code => 200
|
12
|
+
)
|
13
|
+
Typhoeus::Request.expects(:get).with do |url, options|
|
14
|
+
url.should == 'http://us.wowarmory.com/character-sheet.xml'
|
15
|
+
options[:params].should == { :r => 'detheroc', :n => 'hunter' }
|
16
|
+
end.returns(response)
|
17
|
+
|
18
|
+
result = Armory.character_sheet('us', 'detheroc', 'hunter')
|
19
|
+
|
20
|
+
# Basic information
|
21
|
+
result.should be_instance_of(Armory::Character)
|
22
|
+
end
|
23
|
+
|
24
|
+
xit "should raise appropriate errors if the armory is not available"
|
25
|
+
xit "should raise appropriate errors if the rate limit has been reached"
|
26
|
+
|
27
|
+
it "should raise appropriate errors if the character cannot be found" do
|
28
|
+
response = stub(
|
29
|
+
:body => '',
|
30
|
+
:code => 404
|
31
|
+
)
|
32
|
+
Typhoeus::Request.expects(:get).returns(response)
|
33
|
+
|
34
|
+
lambda do
|
35
|
+
Armory.character_sheet('us', 'detheroc', 'hunter')
|
36
|
+
end.should raise_exception(Armory::CharacterNotFound)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#guild_info" do
|
41
|
+
|
42
|
+
it "should properly parse a guild" do
|
43
|
+
response = stub(
|
44
|
+
:body => fixture("guild"),
|
45
|
+
:code => 200
|
46
|
+
)
|
47
|
+
Typhoeus::Request.expects(:get).returns(response)
|
48
|
+
|
49
|
+
result = Armory.guild_info('us', 'detheroc', 'ZeeGuild')
|
50
|
+
|
51
|
+
result.name.should == "ZeeGuild"
|
52
|
+
result.realm.should == "Detheroc"
|
53
|
+
|
54
|
+
result.faction.should == "Horde"
|
55
|
+
result.faction_id.should == 1
|
56
|
+
|
57
|
+
result.characters.length.should == 7
|
58
|
+
|
59
|
+
awesome = result.characters.find {|c| c.name == "MrAwesome" }
|
60
|
+
|
61
|
+
awesome.class_name.should == "Mage"
|
62
|
+
awesome.class_id.should == 8
|
63
|
+
|
64
|
+
awesome.race.should == "Troll"
|
65
|
+
awesome.race_id.should == 8
|
66
|
+
|
67
|
+
awesome.level.should == 36
|
68
|
+
awesome.rank.should == 1
|
69
|
+
|
70
|
+
awesome.gender.should == "Male"
|
71
|
+
awesome.gender_id.should == 0
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should raise error if guild not found" do
|
75
|
+
response = stub(
|
76
|
+
:body => '',
|
77
|
+
:code => 404
|
78
|
+
)
|
79
|
+
Typhoeus::Request.expects(:get).returns(response)
|
80
|
+
|
81
|
+
lambda do
|
82
|
+
Armory.guild_info('us', 'detheroc', 'ZeeGuild')
|
83
|
+
end.should raise_exception(Armory::GuildNotFound)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Armory::Character do
|
4
|
+
before(:all) do
|
5
|
+
@character = Armory::Character.from_armory(Nokogiri::XML(fixture('hunter')))
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should properly parse the base stats" do
|
9
|
+
# Basic information
|
10
|
+
@character.name.should == 'Hunter'
|
11
|
+
@character.level.should == 80
|
12
|
+
@character.class_name.should == 'Hunter'
|
13
|
+
@character.class_id.should == 3
|
14
|
+
@character.guild.should == 'Exiled'
|
15
|
+
@character.last_modified.should == Date.parse('2010/10/13')
|
16
|
+
|
17
|
+
# Faction
|
18
|
+
@character.faction.should == 'Horde'
|
19
|
+
@character.faction_id.should == 1
|
20
|
+
|
21
|
+
# Race
|
22
|
+
@character.race.should == 'Orc'
|
23
|
+
@character.race_id.should == 2
|
24
|
+
|
25
|
+
# Gender
|
26
|
+
@character.gender.should == 'Male'
|
27
|
+
@character.gender_id.should == 0
|
28
|
+
|
29
|
+
# Server
|
30
|
+
@character.realm.should == 'Detheroc'
|
31
|
+
@character.battle_group.should == 'Shadowburn'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should parse the list of items" do
|
35
|
+
@character.items.size.should == 18
|
36
|
+
|
37
|
+
# Validate that at least one has parsed correctly
|
38
|
+
@character.items.first.tap do |item|
|
39
|
+
# Basic information
|
40
|
+
item.id.should == 51286
|
41
|
+
item.name.should == "Sanctified Ahn'Kahar Blood Hunter's Headpiece"
|
42
|
+
item.level.should == 277
|
43
|
+
item.slot.should == 0
|
44
|
+
item.rarity.should == 4
|
45
|
+
|
46
|
+
# Enchants, gems, and durability
|
47
|
+
item.durability.should == 99
|
48
|
+
item.max_durability.should == 100
|
49
|
+
item.enchant_id.should == 44149
|
50
|
+
item.gems.should == [ 41398, 40112 ]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Bounds check with last item in list
|
54
|
+
@character.items.last.tap do |item|
|
55
|
+
# Basic information
|
56
|
+
item.id.should == 52252
|
57
|
+
item.name.should == "Tabard of the Lightbringer"
|
58
|
+
item.level.should == 80
|
59
|
+
item.slot.should == 18
|
60
|
+
item.rarity.should == 4
|
61
|
+
|
62
|
+
# Enchants, gems, and durability
|
63
|
+
item.durability.should == 0
|
64
|
+
item.max_durability.should == 0
|
65
|
+
item.enchant_id.should == 0
|
66
|
+
item.gems.should == []
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/_layout/guild/roster.xsl"?><page globalSearch="1" lang="en_us" requestUrl="/guild-info.xml">
|
2
|
+
<tabInfo subTab="guildRoster" tab="guild" tabGroup="character" tabUrl="r=Detheroc&gn=ZeeGuild"/>
|
3
|
+
<guildInfo>
|
4
|
+
<guildHeader battleGroup="Shadowburn" count="252" faction="1" name="ZeeGuild" nameUrl="ZeeGuild" realm="Detheroc" realmUrl="Detheroc" url="r=Detheroc&gn=ZeeGuild">
|
5
|
+
<emblem emblemBackground="44" emblemBorderColor="15" emblemBorderStyle="3" emblemIconColor="14" emblemIconStyle="122"/>
|
6
|
+
</guildHeader>
|
7
|
+
<guild>
|
8
|
+
<members memberCount="7">
|
9
|
+
<character achPoints="180" classId="8" genderId="0" level="36" name="MrAwesome" raceId="8" rank="1" url="r=Detheroc&cn=MrAwesome"/>
|
10
|
+
<character achPoints="4700" classId="1" genderId="0" level="80" name="OldMan" raceId="5" rank="2" url="r=Detheroc&cn=OldMan"/>
|
11
|
+
<character achPoints="1835" classId="2" genderId="0" level="80" name="Arguer" raceId="6" rank="3" url="r=Detheroc&cn=Arguer"/>
|
12
|
+
<character achPoints="50" classId="3" genderId="1" level="15" name="Leet" raceId="10" rank="4" url="r=Detheroc&cn=Boshlol"/>
|
13
|
+
<character achPoints="5830" classId="4" genderId="0" level="80" name="SillyPerson" raceId="2" rank="5" url="r=Detheroc&cn=Boogart"/>
|
14
|
+
<character achPoints="2820" classId="5" genderId="1" level="80" name="Johnson" raceId="5" rank="6" url="r=Detheroc&cn=Johnson"/>
|
15
|
+
<character achPoints="1435" classId="11" genderId="0" level="80" name="Fondu" raceId="6" rank="7" url="r=Detheroc&cn=Fondu"/>
|
16
|
+
</members>
|
17
|
+
</guild>
|
18
|
+
</guildInfo>
|
19
|
+
</page>
|
@@ -0,0 +1,159 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/_layout/character/sheet.xsl"?><page globalSearch="1" lang="en_us" requestUrl="/character-sheet.xml">
|
2
|
+
<tabInfo subTab="profile" tab="character" tabGroup="character" tabUrl="r=Detheroc&cn=Hunter&gn=Exiled"/>
|
3
|
+
<characterInfo>
|
4
|
+
<character battleGroup="Shadowburn" charUrl="r=Detheroc&cn=Hunter" class="Hunter" classId="3" classUrl="c=Hunter" faction="Horde" factionId="1" gender="Male" genderId="0" guildName="Exiled" guildUrl="r=Detheroc&gn=Exiled" lastModified="October 13, 2010" level="80" name="Hunter" points="9020" prefix="" race="Orc" raceId="2" realm="Detheroc" suffix=", Bane of the Fallen King" titleId="139">
|
5
|
+
<modelBasePath value="http://us.media.battle.net.edgesuite.net/"/>
|
6
|
+
</character>
|
7
|
+
<characterTab>
|
8
|
+
<talentSpecs>
|
9
|
+
<talentSpec group="2" icon="ability_hunter_camouflage" prim="Survival" treeOne="3" treeThree="31" treeTwo="2"/>
|
10
|
+
<talentSpec active="1" group="1" icon="ability_hunter_focusedaim" prim="Marksmanship" treeOne="3" treeThree="2" treeTwo="31"/>
|
11
|
+
</talentSpecs>
|
12
|
+
<buffs/>
|
13
|
+
<debuffs/>
|
14
|
+
<pvp>
|
15
|
+
<lifetimehonorablekills value="5348"/>
|
16
|
+
<arenacurrency value="0"/>
|
17
|
+
</pvp>
|
18
|
+
<professions>
|
19
|
+
<skill id="164" key="blacksmithing" max="450" name="Blacksmithing" value="450"/>
|
20
|
+
<skill id="202" key="engineering" max="450" name="Engineering" value="450"/>
|
21
|
+
</professions>
|
22
|
+
<secondaryProfessions>
|
23
|
+
<skill id="185" key="cooking" max="450" name="Cooking" value="450"/>
|
24
|
+
<skill id="129" key="firstaid" max="450" name="First Aid" value="450"/>
|
25
|
+
</secondaryProfessions>
|
26
|
+
<characterBars>
|
27
|
+
<health effective="30984"/>
|
28
|
+
<secondBar casting="0" effective="0" notCasting="18" type="m"/>
|
29
|
+
</characterBars>
|
30
|
+
<baseStats>
|
31
|
+
<strength attack="232" base="77" block="-1" effective="242"/>
|
32
|
+
<agility armor="5018" attack="2499" base="186" critHitPercent="28.63" effective="2509"/>
|
33
|
+
<stamina base="129" effective="2384" health="23660" petBonus="715"/>
|
34
|
+
<intellect base="87" critHitPercent="0.00" effective="97" mana="1175" petBonus="-1"/>
|
35
|
+
<spirit base="99" effective="109" healthRegen="17" manaRegen="17"/>
|
36
|
+
<armor base="12225" effective="12225" percent="44.52" petBonus="4279"/>
|
37
|
+
</baseStats>
|
38
|
+
<resistances>
|
39
|
+
<arcane petBonus="0" value="0"/>
|
40
|
+
<fire petBonus="0" value="0"/>
|
41
|
+
<frost petBonus="0" value="0"/>
|
42
|
+
<holy petBonus="0" value="0"/>
|
43
|
+
<nature petBonus="0" value="0"/>
|
44
|
+
<shadow petBonus="0" value="0"/>
|
45
|
+
</resistances>
|
46
|
+
<melee>
|
47
|
+
<mainHandDamage dps="687.3" max="2163" min="1720" percent="0" speed="2.83"/>
|
48
|
+
<offHandDamage dps="147.9" max="246" min="245" percent="0" speed="1.66"/>
|
49
|
+
<mainHandSpeed hastePercent="20.37" hasteRating="668" value="2.83"/>
|
50
|
+
<offHandSpeed hastePercent="20.37" hasteRating="668" value="1.66"/>
|
51
|
+
<power base="3180" effective="3434" increasedDps="245.0"/>
|
52
|
+
<hitRating increasedHitPercent="8.16" penetration="0" reducedArmorPercent="0.00" value="251"/>
|
53
|
+
<critChance percent="66.10" plusPercent="37.47" rating="1720"/>
|
54
|
+
<expertise additional="0" percent="0.00" rating="0" value="0"/>
|
55
|
+
</melee>
|
56
|
+
<ranged>
|
57
|
+
<weaponSkill rating="0" value="0"/>
|
58
|
+
<damage dps="942.3" max="2423" min="1875" percent="0" speed="2.28"/>
|
59
|
+
<speed hastePercent="20.37" hasteRating="668" value="2.28"/>
|
60
|
+
<power base="5674" effective="6186" increasedDps="441.0" petAttack="1360.92" petSpell="796.14"/>
|
61
|
+
<hitRating increasedHitPercent="8.16" penetration="0" reducedArmorPercent="0.00" value="251"/>
|
62
|
+
<critChance percent="66.97" plusPercent="38.34" rating="1760"/>
|
63
|
+
</ranged>
|
64
|
+
<spell>
|
65
|
+
<bonusDamage>
|
66
|
+
<arcane value="87"/>
|
67
|
+
<fire value="87"/>
|
68
|
+
<frost value="87"/>
|
69
|
+
<holy value="87"/>
|
70
|
+
<nature value="87"/>
|
71
|
+
<shadow value="87"/>
|
72
|
+
<petBonus attack="-1" damage="-1" fromType=""/>
|
73
|
+
</bonusDamage>
|
74
|
+
<bonusHealing value="87"/>
|
75
|
+
<hitRating increasedHitPercent="9.57" penetration="0" reducedResist="0" value="251"/>
|
76
|
+
<critChance rating="1720">
|
77
|
+
<arcane percent="37.47"/>
|
78
|
+
<fire percent="37.47"/>
|
79
|
+
<frost percent="37.47"/>
|
80
|
+
<holy percent="37.47"/>
|
81
|
+
<nature percent="37.47"/>
|
82
|
+
<shadow percent="37.47"/>
|
83
|
+
</critChance>
|
84
|
+
<penetration value="0"/>
|
85
|
+
<manaRegen casting="0.00" notCasting="18.00"/>
|
86
|
+
<hasteRating hastePercent="20.37" hasteRating="668"/>
|
87
|
+
</spell>
|
88
|
+
<defenses>
|
89
|
+
<armor base="12225" effective="12225" percent="44.52" petBonus="4279"/>
|
90
|
+
<defense decreasePercent="0.00" increasePercent="0.00" plusDefense="0" rating="0" value="-1.00"/>
|
91
|
+
<dodge increasePercent="0.00" percent="22.78" rating="0"/>
|
92
|
+
<parry increasePercent="0.00" percent="5.00" rating="0"/>
|
93
|
+
<block increasePercent="0.00" percent="0.00" rating="0"/>
|
94
|
+
<resilience damagePercent="0" hitPercent="0" value="0.00"/>
|
95
|
+
</defenses>
|
96
|
+
<items>
|
97
|
+
<item displayInfoId="65131" durability="99" gem0Id="41398" gem1Id="40112" gem2Id="0" gemIcon0="inv_jewelcrafting_shadowspirit_02" gemIcon1="inv_jewelcrafting_gem_37" icon="inv_helmet_158" id="51286" level="277" maxDurability="100" name="Sanctified Ahn'Kahar Blood Hunter's Headpiece" permanentEnchantIcon="ability_warrior_rampage" permanentEnchantItemId="44149" permanentenchant="3817" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="0" slot="0"/>
|
98
|
+
<item displayInfoId="64216" durability="0" gem0Id="40125" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_42" icon="inv_misc_monsterhorn_03" id="50421" level="264" maxDurability="0" name="Sindragosa's Cruel Claw" permanentenchant="0" pickUp="PickUpRing" putDown="PutDownRing" randomPropertiesId="0" rarity="4" seed="1837907072" slot="1"/>
|
99
|
+
<item displayInfoId="64829" durability="100" gem0Id="40157" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_40" icon="inv_shoulder_113" id="51288" level="277" maxDurability="100" name="Sanctified Ahn'Kahar Blood Hunter's Spaulders" permanentEnchantIcon="inv_axe_85" permanentEnchantItemId="44871" permanentenchant="3808" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="0" slot="2"/>
|
100
|
+
<item displayInfoId="53421" durability="0" gem0Id="0" gem1Id="0" gem2Id="0" icon="inv_shirt_blue_01" id="42374" level="1" maxDurability="0" name="Blue Martial Shirt" permanentenchant="0" pickUp="" putDown="" randomPropertiesId="0" rarity="1" seed="0" slot="3"/>
|
101
|
+
<item displayInfoId="64840" durability="164" gem0Id="40112" gem1Id="40125" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_37" gemIcon1="inv_jewelcrafting_gem_42" icon="inv_chest_mail_11" id="51289" level="277" maxDurability="165" name="Sanctified Ahn'Kahar Blood Hunter's Tunic" permanentEnchantIcon="inv_scroll_03" permanentEnchantItemId="44465" permanentenchant="3832" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="0" slot="4"/>
|
102
|
+
<item displayInfoId="64837" durability="55" gem0Id="40147" gem1Id="40112" gem2Id="40117" gemIcon0="inv_jewelcrafting_gem_39" gemIcon1="inv_jewelcrafting_gem_37" gemIcon2="inv_jewelcrafting_gem_38" icon="inv_belt_60" id="50688" level="277" maxDurability="55" name="Nerub'ar Stalker's Cord" permanentenchant="0" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="2020223488" slot="5"/>
|
103
|
+
<item displayInfoId="64832" durability="119" gem0Id="40157" gem1Id="40112" gem2Id="40117" gemIcon0="inv_jewelcrafting_gem_40" gemIcon1="inv_jewelcrafting_gem_37" gemIcon2="inv_jewelcrafting_gem_38" icon="inv_pants_mail_32" id="50645" level="277" maxDurability="120" name="Leggings of Northern Lights" permanentEnchantIcon="inv_misc_armorkit_33" permanentEnchantItemId="38374" permanentenchant="3823" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="-1833513728" slot="6"/>
|
104
|
+
<item displayInfoId="65410" durability="75" gem0Id="40112" gem1Id="40125" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_37" gemIcon1="inv_jewelcrafting_gem_42" icon="inv_boots_mail_06" id="49897" level="264" maxDurability="75" name="Rock-Steady Treads" permanentenchant="0" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="1208919808" slot="7"/>
|
105
|
+
<item displayInfoId="64831" durability="54" gem0Id="40125" gem1Id="40112" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_42" gemIcon1="inv_jewelcrafting_gem_37" icon="inv_bracer_40" id="50655" level="277" maxDurability="55" name="Scourge Hunter's Vambraces" permanentEnchantIcon="inv_scroll_03" permanentEnchantItemId="44815" permanentenchant="3845" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="2028935680" slot="8"/>
|
106
|
+
<item displayInfoId="64823" durability="55" gem0Id="40112" gem1Id="40117" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_37" gemIcon1="inv_jewelcrafting_gem_38" icon="inv_gauntlets_84" id="51154" level="264" maxDurability="55" name="Sanctified Ahn'Kahar Blood Hunter's Handguards" permanentenchant="0" pickUp="PickUpSmallChain" putDown="PutDownSmallChain" randomPropertiesId="0" rarity="4" seed="0" slot="9"/>
|
107
|
+
<item displayInfoId="63958" durability="0" gem0Id="40147" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_39" icon="inv_jewelry_ring_81" id="50402" level="277" maxDurability="0" name="Ashen Band of Endless Vengeance" permanentenchant="0" pickUp="PickUpMetalSmall" putDown="PutDownSmallMEtal" randomPropertiesId="0" rarity="4" seed="2003437696" slot="10"/>
|
108
|
+
<item displayInfoId="64227" durability="0" gem0Id="40112" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_37" icon="item_icecrownringa" id="50186" level="264" maxDurability="0" name="Frostbrood Sapphire Ring" permanentenchant="0" pickUp="PickUpRing" putDown="PutDownRing" randomPropertiesId="0" rarity="4" seed="1445969664" slot="11"/>
|
109
|
+
<item displayInfoId="64244" durability="0" gem0Id="0" gem1Id="0" gem2Id="0" icon="inv_jewelry_trinket_04" id="50362" level="264" maxDurability="0" name="Deathbringer's Will" permanentenchant="0" pickUp="PickUpWand" putDown="PutDownWand" randomPropertiesId="0" rarity="4" seed="639932288" slot="12"/>
|
110
|
+
<item displayInfoId="70525" durability="0" gem0Id="0" gem1Id="0" gem2Id="0" icon="inv_misc_rubysanctum4" id="54569" level="271" maxDurability="0" name="Sharpened Twilight Scale" permanentenchant="0" pickUp="PickUpGems" putDown="PutDownGems" randomPropertiesId="0" rarity="4" seed="955881728" slot="13"/>
|
111
|
+
<item displayInfoId="64304" durability="0" gem0Id="40147" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_39" icon="item_icecrowncloak" id="50653" level="277" maxDurability="0" name="Shadowvault Slayer's Cloak" permanentenchant="0" pickUp="PickUpCloth_Leather01" putDown="PutDownCloth_Leather01" randomPropertiesId="0" rarity="4" seed="-2108600704" slot="14"/>
|
112
|
+
<item displayInfoId="64554" durability="120" gem0Id="40112" gem1Id="40125" gem2Id="40147" gemIcon0="inv_jewelcrafting_gem_37" gemIcon1="inv_jewelcrafting_gem_42" gemIcon2="inv_jewelcrafting_gem_39" icon="inv_weapon_staff_109" id="50727" level="277" maxDurability="120" name="Bloodfall" permanentenchant="0" pickUp="PickUpMetalLArge" putDown="PutDownLArgeMEtal" randomPropertiesId="0" rarity="4" seed="419746256" slot="15"/>
|
113
|
+
<item displayInfoId="64356" durability="88" gem0Id="40112" gem1Id="0" gem2Id="0" gemIcon0="inv_jewelcrafting_gem_37" icon="inv_weapon_bow_55" id="50638" level="277" maxDurability="90" name="Zod's Repeating Longbow" permanentEnchantIcon="inv_misc_spyglass_02" permanentEnchantItemId="41167" permanentenchant="3608" pickUp="PickUpWoodSmall" putDown="PutDownWoodSmall" randomPropertiesId="0" rarity="4" seed="-2014464000" slot="17"/>
|
114
|
+
<item displayInfoId="65733" durability="0" gem0Id="0" gem1Id="0" gem2Id="0" icon="inv_shirt_guildtabard_01" id="52252" level="80" maxDurability="0" name="Tabard of the Lightbringer" permanentenchant="0" pickUp="PickUpCloth_Leather01" putDown="PutDownCloth_Leather01" randomPropertiesId="0" rarity="4" seed="149955648" slot="18"/>
|
115
|
+
</items>
|
116
|
+
<glyphs>
|
117
|
+
<glyph effect="Increases the healing done by your Mend Pet ability by an additional 3%." icon="ability_hunter_mendpet" id="354" name="Glyph of Mending" type="major"/>
|
118
|
+
<glyph effect="Your Mend Pet spell increases your pet's happiness slightly." icon="ability_hunter_mendpet" id="440" name="Glyph of Mend Pet" type="minor"/>
|
119
|
+
<glyph effect="Reduces the cooldown of your Feign Death spell by 5 sec." icon="ability_rogue_feigndeath" id="441" name="Glyph of Feign Death" type="minor"/>
|
120
|
+
<glyph effect="Decreases the cooldown of Disengage by 5 sec." icon="ability_rogue_feint" id="358" name="Glyph of Disengage" type="major"/>
|
121
|
+
<glyph effect="Reduces the pushback suffered from damaging attacks while casting Revive Pet by 100%." icon="ability_hunter_beastsoothe" id="439" name="Glyph of Revive Pet" type="minor"/>
|
122
|
+
<glyph effect="Reduces the focus cost of Trap Launcher by 10." icon="ability_hunter_traplauncher" id="353" name="Glyph of Trap Launcher" type="major"/>
|
123
|
+
<glyph effect="Increases the damage dealt by Steady Shot by 10%." icon="ability_hunter_steadyshot" id="368" name="Glyph of Steady Shot" type="major"/>
|
124
|
+
<glyph effect="If the damage from your Kill Shot fails to kill a target at or below 20% health, your Kill Shot's cooldown is instantly reset. This effect has a 6 sec cooldown." icon="ability_hunter_assassinate2" id="692" name="Glyph of Kill Shot" type="major"/>
|
125
|
+
<glyph effect="Your Arcane Shot deals 12% more damage." icon="ability_impalingbolt" id="352" name="Glyph of Arcane Shot" type="major"/>
|
126
|
+
</glyphs>
|
127
|
+
</characterTab>
|
128
|
+
<summary>
|
129
|
+
<c earned="838" points="9020" total="1056" totalPoints="11640"/>
|
130
|
+
<category id="92" name="General">
|
131
|
+
<c earned="47" earnedPoints="485" total="52" totalPoints="535"/>
|
132
|
+
</category>
|
133
|
+
<category id="96" name="Quests">
|
134
|
+
<c earned="49" earnedPoints="530" total="49" totalPoints="530"/>
|
135
|
+
</category>
|
136
|
+
<category id="97" name="Exploration">
|
137
|
+
<c earned="68" earnedPoints="780" total="70" totalPoints="830"/>
|
138
|
+
</category>
|
139
|
+
<category id="95" name="Player vs. Player">
|
140
|
+
<c earned="56" earnedPoints="570" total="166" totalPoints="1930"/>
|
141
|
+
</category>
|
142
|
+
<category id="168" name="Dungeons & Raids">
|
143
|
+
<c earned="389" earnedPoints="4220" total="458" totalPoints="4955"/>
|
144
|
+
</category>
|
145
|
+
<category id="169" name="Professions">
|
146
|
+
<c earned="67" earnedPoints="670" total="75" totalPoints="760"/>
|
147
|
+
</category>
|
148
|
+
<category id="201" name="Reputation">
|
149
|
+
<c earned="27" earnedPoints="335" total="45" totalPoints="560"/>
|
150
|
+
</category>
|
151
|
+
<category id="155" name="World Events">
|
152
|
+
<c earned="135" earnedPoints="1430" total="141" totalPoints="1540"/>
|
153
|
+
</category>
|
154
|
+
<category id="81" name="Feats of Strength">
|
155
|
+
<c earned="14"/>
|
156
|
+
</category>
|
157
|
+
</summary>
|
158
|
+
</characterInfo>
|
159
|
+
</page>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require 'rspec'
|
4
|
+
require 'armory'
|
5
|
+
|
6
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
7
|
+
# in spec/support/ and its subdirectories.
|
8
|
+
Dir[File.expand_path("../spec/support/**/*.rb", __FILE__)].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
# == Mock Framework
|
12
|
+
# config.mock_with :mocha
|
13
|
+
config.mock_with :mocha
|
14
|
+
|
15
|
+
def fixture(fixture)
|
16
|
+
File.read(File.expand_path("../fixtures/#{fixture}.xml", __FILE__))
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: armory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Chris Gaffney
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-13 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 1
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 4
|
31
|
+
- 3
|
32
|
+
version: 1.4.3
|
33
|
+
requirement: *id001
|
34
|
+
type: :runtime
|
35
|
+
name: nokogiri
|
36
|
+
prerelease: false
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 23
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 2
|
47
|
+
- 0
|
48
|
+
version: 0.2.0
|
49
|
+
requirement: *id002
|
50
|
+
type: :runtime
|
51
|
+
name: typhoeus
|
52
|
+
prerelease: false
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 11
|
60
|
+
segments:
|
61
|
+
- 2
|
62
|
+
- 1
|
63
|
+
- 0
|
64
|
+
version: 2.1.0
|
65
|
+
requirement: *id003
|
66
|
+
type: :development
|
67
|
+
name: rspec
|
68
|
+
prerelease: false
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 41
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
- 9
|
79
|
+
- 9
|
80
|
+
version: 0.9.9
|
81
|
+
requirement: *id004
|
82
|
+
type: :development
|
83
|
+
name: mocha
|
84
|
+
prerelease: false
|
85
|
+
description:
|
86
|
+
email:
|
87
|
+
- gaffneyc@gmail.com
|
88
|
+
executables: []
|
89
|
+
|
90
|
+
extensions: []
|
91
|
+
|
92
|
+
extra_rdoc_files: []
|
93
|
+
|
94
|
+
files:
|
95
|
+
- lib/armory/character.rb
|
96
|
+
- lib/armory/guild.rb
|
97
|
+
- lib/armory/version.rb
|
98
|
+
- lib/armory.rb
|
99
|
+
- spec/armory_spec.rb
|
100
|
+
- spec/character_spec.rb
|
101
|
+
- spec/fixtures/guild.xml
|
102
|
+
- spec/fixtures/hunter.xml
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
- LICENSE
|
105
|
+
- README.rdoc
|
106
|
+
has_rdoc: true
|
107
|
+
homepage: http://github.com/gaffneyc/armory
|
108
|
+
licenses: []
|
109
|
+
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
hash: 3
|
130
|
+
segments:
|
131
|
+
- 0
|
132
|
+
version: "0"
|
133
|
+
requirements: []
|
134
|
+
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 1.3.7
|
137
|
+
signing_key:
|
138
|
+
specification_version: 3
|
139
|
+
summary: Library for downloading and parsing the wow armory
|
140
|
+
test_files: []
|
141
|
+
|