pwood-wowr 0.5.1

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.
@@ -0,0 +1,143 @@
1
+ module Wowr
2
+ module Classes
3
+ class CharacterAchievementsInfo
4
+ attr_reader :latest_achievements, :categories
5
+
6
+ def initialize elem, api
7
+ @api = api
8
+ @latest_achievements = Array.new
9
+ @categories = Array.new
10
+
11
+ achievements = elem%'achievements'
12
+ summary = achievements%'summary'
13
+
14
+ # Get list of latest achievements
15
+ summary.search('achievement').each do |achievement|
16
+ @latest_achievements << CompletedAchievement.new(achievement)
17
+ end
18
+
19
+ # Get the infos about categories completion
20
+ # They are ordered in same order as categories below
21
+ categories_completion = summary.search('category/c')
22
+
23
+ # Get the list of rootCategories
24
+ i = 0
25
+ achievements.search('rootCategories/category').each do |category|
26
+ elem = Hash.new
27
+ type = AchievementsCategoryDetails
28
+ elem['id'] = category['id']
29
+ elem['name'] = category['name']
30
+ completion = categories_completion[i]
31
+ elem['earned'] = completion['earned']
32
+
33
+ # If we have more informations
34
+ if completion['total']
35
+ type = AchievementsCategoryDetailsWithPoints
36
+ elem['total'] = completion['total']
37
+ elem['totalPoints'] = completion['totalPoints']
38
+ elem['earnedPoints'] = completion['earnedPoints']
39
+ end
40
+ new_cat = type.new(elem)
41
+
42
+ # Add subcategories
43
+ category.search('category').each do |subcategory|
44
+ subcat = AchievementsCategory.new subcategory
45
+ new_cat.add_subcategory subcat
46
+ end
47
+
48
+ @categories << new_cat
49
+ i = i+1
50
+ end
51
+ end
52
+ end
53
+
54
+ class Achievement
55
+ attr_reader :desc, :title, :category_id, :icon, :id, :points, :reward
56
+ def initialize achievement
57
+ @desc = achievement['desc']
58
+ @category_id = achievement['categoryId'].to_i
59
+ @icon = achievement['icon']
60
+ @id = achievement['id'].to_i
61
+
62
+ if achievement['points']
63
+ @points = achievement['points'].to_i
64
+ else
65
+ @points = nil
66
+ end
67
+
68
+ if achievement['reward']
69
+ @reward = achievement['reward']
70
+ else
71
+ @reward = nil
72
+ end
73
+
74
+ @title = achievement['title']
75
+ end
76
+ end
77
+
78
+ class CompletedAchievement < Achievement
79
+ attr_reader :date_completed
80
+ def initialize achievement
81
+ super(achievement)
82
+ @date_completed = achievement['dateCompleted']
83
+ begin
84
+ @date_completed = achievement[:dateCompleted] == "" ? nil : DateTime.parse(achievement[:dateCompleted])
85
+ rescue
86
+ @date_completed = achievement[:dateCompleted] == "" ? nil : achievement[:dateCompleted]
87
+ end
88
+ end
89
+ end
90
+
91
+ class AchievementsCategory
92
+ attr_reader :name
93
+ attr_reader :subcategories
94
+ attr_reader :id
95
+ attr_writer :parent
96
+ def initialize category
97
+ @name = category['name']
98
+ @id = category['id'].to_i if category['id']
99
+ @subcategories = Array.new
100
+ end
101
+
102
+ def add_subcategory category
103
+ @subcategories << category
104
+ category.parent = self
105
+ end
106
+ end
107
+
108
+ class AchievementsCategoryDetails < AchievementsCategory
109
+ attr_reader :earned
110
+ def initialize category
111
+ super(category)
112
+ @earned = category['earned'].to_i
113
+ end
114
+ end
115
+
116
+ class AchievementsCategoryDetailsWithPoints < AchievementsCategoryDetails
117
+ attr_reader :earned_points, :total, :total_points
118
+ def initialize category
119
+ super(category)
120
+ @earned_points = category['earnedPoints'].to_i
121
+ @total = category['total'].to_i
122
+ @total_points = category['totalPoints'].to_i
123
+ end
124
+ end
125
+
126
+ class AchievementsList
127
+ attr_reader :achievements
128
+ def initialize elem, api
129
+ @api = api
130
+ @achievements = Array.new
131
+ elem.search('achievement').each do |achievement|
132
+ if achievement['dateCompleted']
133
+ new_achievement = CompletedAchievement.new(achievement)
134
+ else
135
+ new_achievement = Achievement.new(achievement)
136
+ end
137
+ @achievements << new_achievement
138
+
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,80 @@
1
+ module Wowr
2
+ module Classes
3
+ class ArenaTeam
4
+ attr_reader :name, :size, :battle_group, :faction, :faction_id, :realm, :realm_url,
5
+ :games_played, :games_won, :ranking, :rating,
6
+ :season_games_played, :season_games_won, :last_season_ranking,
7
+ :relevance, :url, :url_escape,
8
+ :characters, # can be blank on search results
9
+ :emblem
10
+ alias_method :to_s, :name
11
+
12
+ def initialize(elem)
13
+ @name = elem[:name]
14
+ @size = elem[:size].to_i
15
+ @battle_group = elem[:battleGroup]
16
+ @faction = elem[:faction]
17
+ @faction_id = elem[:factionId].to_i
18
+ @realm = elem[:realm]
19
+ @realm_url = elem[:realmUrl]
20
+
21
+ @games_played = elem[:gamesPlayed].to_i
22
+ @games_won = elem[:gamesWon].to_i
23
+ # @ranking = elem[:ranking].to_i # Ranking in the seach results is always 0
24
+ @rating = elem[:rating].to_i
25
+
26
+ @season_games_played = elem[:seasonGamesPlayed].to_i
27
+ @season_games_won = elem[:seasonGamesWon].to_i
28
+ @last_season_ranking = elem[:lastSeasonRanking].to_i
29
+
30
+ @relevance = elem[:relevance].to_i
31
+ @url = elem[:url]
32
+
33
+ @emblem = ArenaTeamEmblem.new(elem%'emblem')
34
+ end
35
+ end
36
+
37
+
38
+ class SearchArenaTeam < ArenaTeam
39
+ def initialize(elem)
40
+ super(elem)
41
+ end
42
+ end
43
+
44
+ # <teamInfo>
45
+ # <arenaTeam battleGroup="Vindication" faction="Alliance" factionId="0" gamesPlayed="6" gamesWon="1" lastSeasonRanking="4118" name="Monkey" ranking="6522" rating="1535" realm="Burning Blade" realmUrl="b=Vindication&amp;r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;ff=realm&amp;fv=Burning+Blade&amp;select=Monkey" relevance="0" seasonGamesPlayed="66" seasonGamesWon="34" size="2" url="r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;select=Monkey" urlEscape="r=Burning+Blade&amp;ts=2&amp;t=Monkey&amp;select=Monkey">
46
+ # <emblem background="ff70de56" borderColor="ffcc73eb" borderStyle="6" iconColor="ffe3b320" iconStyle="44"/>
47
+ # <members>
48
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Fandiar" class="Priest" classId="5" contribution="1380" gamesPlayed="0" gamesWon="0" gender="Male" genderId="0" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Fandiar" race="Night Elf" raceId="4" realm="Burning Blade" seasonGamesPlayed="18" seasonGamesWon="1" teamRank="0"/>
49
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Stayfrosty" class="Mage" classId="8" contribution="1460" gamesPlayed="6" gamesWon="1" gender="Male" genderId="0" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Stayfrosty" race="Human" raceId="1" realm="Burning Blade" seasonGamesPlayed="6" seasonGamesWon="1" teamRank="1"/>
50
+ # <character battleGroup="Vindication" charUrl="r=Burning+Blade&amp;n=Step" class="Rogue" classId="4" contribution="1688" gamesPlayed="2" gamesWon="1" gender="Female" genderId="1" guild="Legends" guildId="916" guildUrl="r=Burning+Blade&amp;n=Legends&amp;p=1" name="Step" race="Human" raceId="1" realm="Burning Blade" seasonGamesPlayed="44" seasonGamesWon="33" teamRank="1"/>
51
+ # </members>
52
+ # </arenaTeam>
53
+ # </teamInfo>
54
+ class FullArenaTeam < ArenaTeam
55
+
56
+ def initialize(elem)
57
+ super(elem)
58
+ # @ranking = elem[:ranking].to_i
59
+
60
+ @members = {}
61
+ (elem%'members'/:character).each do |character|
62
+ @members[character[:name]] = SearchCharacter.new(character)
63
+ end
64
+ end
65
+ end
66
+
67
+ # An arena team's logo
68
+ class ArenaTeamEmblem
69
+ attr_reader :background, :border_color, :border_style, :icon_colour, :icon_style
70
+
71
+ def initialize(elem)
72
+ @background = elem[:background]
73
+ @border_color = elem[:borderColor]
74
+ @border_style = elem[:borderStyle].to_i
75
+ @icon_color = elem[:iconColor]
76
+ @icon_style = elem[:iconStyle].to_i
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,78 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ module Wowr
5
+ module Classes
6
+ class CommonCalendar
7
+ attr_reader :summary, :calendar_type, :start, :icon
8
+
9
+ def initialize(json, api = nil)
10
+ @summary = json["summary"]
11
+ @calendar_type = json["calendarType"]
12
+ @start = Time.at((json["start"] / 1000).floor)
13
+ @icon = json["icon"]
14
+ end
15
+ end
16
+
17
+ class WorldCalendar < CommonCalendar
18
+ attr_reader :end, :description, :priority
19
+
20
+ def initialize(json, api = nil)
21
+ super(json, api)
22
+ @end = Time.at((json["end"] / 1000).floor)
23
+ @description = json["description"]
24
+ @priority = json["priority"]
25
+ end
26
+ end
27
+
28
+ class UserCommonCalendar < CommonCalendar
29
+ attr_reader :type, :owner, :moderator, :id
30
+
31
+ def initialize(json, api = nil)
32
+ super(json, api)
33
+ @type = json["type"]
34
+ @owner = json["owner"]
35
+ @moderator = json["moderator"] if json["moderator"]
36
+ @id = json["id"]
37
+ end
38
+ end
39
+
40
+ class UserCalendar < UserCommonCalendar
41
+ attr_reader :inviter, :status
42
+
43
+ def initialize(json, api = nil)
44
+ super(json, api)
45
+ @inviter = json["inviter"]
46
+ @status = json["status"]
47
+ end
48
+ end
49
+
50
+ class UserDetailCalendar < UserCommonCalendar
51
+ attr_reader :locked, :description, :invites
52
+
53
+ def initialize(json, api = nil)
54
+ super(json, api)
55
+ @locked = json["locked"]
56
+ @description = json["description"]
57
+
58
+ @invites = []
59
+
60
+ json["invites"].each do |invitee|
61
+ @invites << UserDetailInvitee.new(invitee, api)
62
+ end
63
+ end
64
+ end
65
+
66
+ class UserDetailInvitee
67
+ attr_reader :class_id, :status, :moderator, :invitee, :id
68
+
69
+ def initialize(json, api = nil)
70
+ @class_id = json["class_id"]
71
+ @status = json["status"]
72
+ @moderator = json["moderator"]
73
+ @invitee = json["invitee"]
74
+ @id = json["id"]
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,832 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'wowr/item.rb'
5
+
6
+ module Wowr
7
+ module Classes
8
+
9
+ # Short character info, used in guild lists etc.
10
+ # Note that the way that searches and character listings within guilds works,
11
+ # there can be a variable amount of information filled in within the class.
12
+ # Guild listings and search results contain a smaller amount of information than
13
+ # single queries
14
+ # Attributes
15
+ # * name (String) - Full character name
16
+ # * level (Fixnum) - Level
17
+ # See Also: Guild
18
+ class Character
19
+ attr_reader :name, :level, :url, :rank,
20
+ :klass, :klass_id,
21
+ :gender, :gender_id,
22
+ :race, :race_id,
23
+ :guild, :guild_id, :guild_url,
24
+ :realm,
25
+ :battle_group, :last_login,
26
+ :relevance, :search_rank,
27
+ :achievement_points,
28
+
29
+ :season_games_played, :season_games_won, :team_rank, :contribution # From ArenaTeam info
30
+
31
+ alias_method :to_s, :name
32
+ alias_method :to_i, :level
33
+
34
+ @@race_icon_url_base = 'images/icons/race/'
35
+ @@class_icon_url_base = 'images/icons/class/'
36
+ @@portrait_url_base = 'images/portraits/'
37
+ @@icon_types = {:default => 'wow-default', 70 => 'wow-70', :other => 'wow'}
38
+
39
+ def initialize(elem, api = nil)
40
+ @api = api
41
+
42
+ @name = elem[:name]
43
+ @level = elem[:level].to_i
44
+ @url = elem[:url] || elem[:charUrl]
45
+ @rank = elem[:rank].to_i
46
+
47
+ @klass = elem[:class]
48
+ @klass_id = elem[:classId].to_i
49
+
50
+ @gender = elem[:gender]
51
+ @gender_id = elem[:genderId].to_i
52
+
53
+ @race = elem[:race]
54
+ @race_id = elem[:raceId].to_i
55
+
56
+ @guild = elem[:guild] == "" ? nil : elem[:guild]
57
+ @guild_id = elem[:guildId].to_i == 0 ? nil : elem[:guildId].to_i
58
+ @guild_url = elem[:guildUrl] == "" ? nil : elem[:guildUrl]
59
+
60
+ @realm = elem[:realm] == "" ? nil : elem[:realm]
61
+
62
+ @battle_group = elem[:battleGroup] == "" ? nil : elem[:battleGroup]
63
+ @battle_group_id = elem[:battleGroupId].to_i
64
+
65
+ @relevance = elem[:relevance].to_i
66
+ @search_rank = elem[:searchRank].to_i
67
+
68
+ @achievement_points = elem[:points].to_i if elem[:points]
69
+ @achievement_points = elem[:achPoints].to_i if elem[:achPoints]
70
+
71
+ # Incoming string is 2007-02-24 20:33:04.0, parse to datetime
72
+ #@last_login = elem[:lastLoginDate] == "" ? nil : DateTime.parse(elem[:lastLoginDate])
73
+ @last_login = elem[:lastLoginDate] == "" ? nil : elem[:lastLoginDate]
74
+
75
+ # From ArenaTeam info, can be blank on normal requests
76
+ #<character battleGroup="" charUrl="r=Draenor&amp;n=Lothaar" class="Paladin" classId="2"
77
+ # contribution="1602" gamesPlayed="10" gamesWon="7" gender="Male" genderId="0"
78
+ # guild="Passion" guildId="36659" guildUrl="r=Draenor&amp;n=Passion&amp;p=1" name="Lothaar"
79
+ # race="Human" raceId="1" seasonGamesPlayed="20" seasonGamesWon="13" teamRank="1"/>
80
+ @season_games_played = elem[:seasonGamesPlayed] == "" ? nil : elem[:seasonGamesPlayed].to_i
81
+ @season_games_won = elem[:seasonGamesWon] == "" ? nil : elem[:seasonGamesWon].to_i
82
+ @team_rank = elem[:teamRank] == "" ? nil : elem[:teamRank].to_i
83
+ @contribution = elem[:contribution] == "" ? nil : elem[:contribution].to_i
84
+ #@char_url = elem[:charUrl] # TODO: Merge with URL?
85
+ end
86
+
87
+
88
+ def icon(type = nil)
89
+ if !type.nil? && !@@icon_types.include?(type)
90
+ raise Wowr::Exceptions::InvalidIconType.new(@@icon_types)
91
+ end
92
+
93
+ if (type.nil?) && (@level == 70)
94
+ dir = @@icon_types[70]
95
+ elsif (type.nil?)
96
+ dir = @@icon_types[:other]
97
+ else
98
+ dir = @@icon_types[type]
99
+ end
100
+
101
+ # http://armory.worldofwarcraft.com/images/portraits/wow-70/1-7-8.gif
102
+ return base + @@portrait_url_base + dir + "/#{@gender_id}-#{@race_id}-#{@klass_id}.gif"
103
+ end
104
+
105
+
106
+ def race_icon
107
+ # http://armory.worldofwarcraft.com/images/icons/race/11-1.gif
108
+ return base + @@race_icon_url_base + "#{@race_id}-#{@gender_id.to_s}.gif"
109
+ end
110
+
111
+
112
+ def class_icon
113
+ # http://armory.worldofwarcraft.com/images/icons/class/8.gif
114
+ return base + @@class_icon_url_base + "#{@klass_id.to_s}.gif"
115
+ end
116
+
117
+
118
+ protected
119
+ def base
120
+ if @api
121
+ return @api.base_url
122
+ else
123
+ return 'http://www.wowarmory.com/'
124
+ end
125
+ end
126
+ end
127
+
128
+ class SearchCharacter < Character
129
+ end
130
+
131
+ # Character details without reputations
132
+ # uses characterInfo element
133
+ # Made up of two parts, character and charactertab
134
+ class InfoCharacter < Character
135
+
136
+ # character_info
137
+ attr_reader :char_url, :title, :known_titles,
138
+ :faction, :faction_id,
139
+ :arena_teams,
140
+ :last_modified,
141
+ :points
142
+
143
+ # character_tab
144
+ attr_reader :health, :second_bar,
145
+ :strength, :agility, :stamina, :intellect, :spirit
146
+ alias_method :str, :strength
147
+ alias_method :agi, :agility
148
+ alias_method :sta, :stamina
149
+ alias_method :int, :intellect
150
+ alias_method :spi, :spirit
151
+
152
+ attr_reader :melee, :ranged, :spell,
153
+ :defenses, :resistances,
154
+ :talent_spec, :all_talent_specs, :pvp,
155
+ :professions,
156
+ :items,
157
+ :buffs, :debuffs
158
+
159
+ # It's made up of two parts
160
+ # Don't care about battlegroups yet
161
+ # I don't think I can call stuff from the constructor?
162
+ def initialize(sheet, api = nil)
163
+ super(sheet%'character', api)
164
+
165
+ @api = api
166
+
167
+ character_info(sheet%'character')
168
+
169
+ # Check if characterTab is defined. If not, the character have no infos on the armory (not logged since last armory wipe)
170
+ raise Wowr::Exceptions::CharacterNoInfo.new(@name) if (sheet%'characterTab').nil?
171
+
172
+ character_tab(sheet%'characterTab')
173
+ end
174
+
175
+ # <character
176
+ # battleGroup="Conviction"
177
+ # charUrl="r=Genjuros&amp;n=Jonlok"
178
+ # class="Warlock"
179
+ # classId="9"
180
+ # faction="Horde"
181
+ # factionId="1"
182
+ # gender="Male"
183
+ # genderId="0"
184
+ # guildName=""
185
+ # lastModified="12 February 2008"
186
+ # level="41"
187
+ # name="Jonlok"
188
+ # prefix=""
189
+ # points="2270"
190
+ # race="Orc"
191
+ # raceId="2"
192
+ # realm="Genjuros"
193
+ # suffix=""/>
194
+
195
+ def character_info(elem)
196
+ # basic info
197
+ @name = elem[:name]
198
+ @level = elem[:level].to_i
199
+ @char_url = elem[:charUrl]
200
+
201
+ @klass = elem[:class]
202
+ @klass_id = elem[:classId].to_i
203
+
204
+ @gender = elem[:gender]
205
+ @gender_id = elem[:genderId].to_i
206
+
207
+ @race = elem[:race]
208
+ @race_id = elem[:raceId].to_i
209
+
210
+ @faction = elem[:faction]
211
+ @faction_id = elem[:factionId].to_i
212
+
213
+ @guild = elem[:guildName] == "" ? nil : elem[:guildName]
214
+ @guild_url = elem[:guildUrl] == "" ? nil : elem[:guildUrl]
215
+
216
+ @prefix = elem[:prefix] == "" ? nil : elem[:prefix]
217
+ @suffix = elem[:suffix] == "" ? nil : elem[:suffix]
218
+
219
+ @points = elem[:points].to_i
220
+
221
+ @realm = elem[:realm]
222
+
223
+ @battle_group = elem[:battleGroup]
224
+
225
+ # format is February 11, 2008
226
+ # except when it's korean, and then it's 2008년 5월 11일 (일)
227
+ # tw is 2008&#24180;5&#26376;11&#26085; (2008年5月11日)
228
+ # TODO: Datetime doesn't parse other languages nicely
229
+ # Until then, just save it as a string
230
+ begin
231
+ @last_modified = elem[:lastModified] == "" ? nil : DateTime.parse(elem[:lastModified])
232
+ rescue
233
+ @last_modified = elem[:lastModified] == "" ? nil : elem[:lastModified]
234
+ end
235
+ #@last_modified = elem[:lastModified]#.to_time
236
+
237
+ @arena_teams = []
238
+ (elem/:arenaTeam).each do |arena_team|
239
+ @arena_teams << ArenaTeam.new(arena_team)
240
+ end
241
+
242
+ end
243
+
244
+ def character_tab(elem)
245
+ # <title value=""/>
246
+ @title = (elem%'title')[:value] == "" ? nil : (elem%'title')[:value]
247
+
248
+ @known_titles = []
249
+
250
+ @known_titles << @title if (@title)
251
+ (elem%'knownTitles'/:title).each do |entry|
252
+ @known_titles << entry[:value] if (!@known_titles.include?(entry[:value]))
253
+ end
254
+
255
+ @health = (elem%'characterBars'%'health')[:effective].to_i
256
+ @second_bar = SecondBar.new(elem%'characterBars'%'secondBar')
257
+
258
+ # base stats
259
+ @strength = Strength.new(elem%'baseStats'%'strength')
260
+ @agility = Agility.new(elem%'baseStats'%'agility')
261
+ @stamina = Stamina.new(elem%'baseStats'%'stamina')
262
+ @intellect = Intellect.new(elem%'baseStats'%'intellect')
263
+ @spirit = Spirit.new(elem%'baseStats'%'spirit')
264
+
265
+ # damage stuff
266
+ @melee = Melee.new(elem%'melee')
267
+ @ranged = Ranged.new(elem%'ranged')
268
+ @spell = Spell.new(elem.at(' > spell')) # TODO: hacky?
269
+ @defenses = Defenses.new(elem%'defenses')
270
+
271
+ # TODO: Massive problem, doesn't fill in resistances for some reason
272
+ resist_types = ['arcane', 'fire', 'frost', 'holy', 'nature', 'shadow']
273
+ @resistances = {}
274
+ resist_types.each do |res|
275
+ @resistances[res] = Resistance.new(elem%'resistances'%res)
276
+ end
277
+
278
+ @all_talent_specs = []
279
+
280
+ (elem%'talentSpecs'/:talentSpec).each do |spec|
281
+ new_spec = TalentSpec.new(spec)
282
+ @all_talent_specs << new_spec
283
+
284
+ @talent_spec = new_spec if (new_spec.active)
285
+ end
286
+
287
+ @pvp = Pvp.new(elem%'pvp')
288
+
289
+ @professions = []
290
+ (elem%'professions'/:skill).each do |skill|
291
+ @professions << Skill.new(skill)
292
+ end
293
+
294
+ @items = []
295
+ (elem%'items'/:item).each do |item|
296
+ @items << EquippedItem.new(item, @api)
297
+ end
298
+
299
+ @buffs = []
300
+ (elem%'buffs'/:spell).each do |buff|
301
+ @buffs << Buff.new(buff, @api)
302
+ end
303
+
304
+ @debuffs = []
305
+ (elem%'debuffs'/:spell).each do |debuff|
306
+ @debuffs << Buff.new(debuff, @api)
307
+ end
308
+ end
309
+ end
310
+
311
+ # Full character details with reputations
312
+ class FullCharacter < InfoCharacter
313
+ attr_reader :reputation_categories
314
+
315
+ alias_method :rep, :reputation_categories
316
+ alias_method :reputation, :reputation_categories
317
+
318
+ def initialize(sheet, reputation, api = nil)
319
+ @api = api
320
+
321
+ # Build the InfoCharacter
322
+ super(sheet, api)
323
+
324
+ # Add reputations
325
+ character_reputation(reputation)
326
+ end
327
+
328
+ # character-reputation.xml
329
+ def character_reputation(elem)
330
+ @reputation_categories = {}
331
+ (elem/:factionCategory).each do |category|
332
+ @reputation_categories[category[:key]] = RepFactionCategory.new(category)
333
+ end
334
+ end
335
+ end
336
+
337
+
338
+ # Second stat bar, depends on character class
339
+ class SecondBar
340
+ attr_reader :effective, :casting, :not_casting, :type
341
+
342
+ def initialize(elem)
343
+ @effective = elem[:effective].to_i
344
+ @casting = elem[:casting].to_i == -1 ? nil : elem[:casting].to_i
345
+ @not_casting = elem[:notCasting].to_i == -1 ? nil : elem[:notCasting].to_i
346
+ @type = elem[:type]
347
+ end
348
+ end
349
+
350
+
351
+ class BaseStat # abstract?
352
+ attr_reader :base, :effective
353
+ end
354
+
355
+ class Strength < BaseStat
356
+ attr_reader :attack, :block
357
+ def initialize(elem)
358
+ @base = elem['base'].to_i
359
+ @effective = elem['effective'].to_i
360
+ @attack = elem['attack'].to_i
361
+ @block = elem['block'].to_i == -1 ? nil : elem['block'].to_i
362
+ end
363
+ end
364
+
365
+ class Agility < BaseStat
366
+ attr_reader :armor, :attack, :crit_hit_percent
367
+ def initialize(elem)
368
+ @base = elem[:base].to_i
369
+ @effective = elem[:effective].to_i
370
+ @armor = elem[:armor].to_i
371
+ @attack = elem[:attack].to_i == -1 ? nil : elem[:attack].to_i
372
+ @crit_hit_percent = elem[:critHitPercent].to_f
373
+ end
374
+ end
375
+
376
+ class Stamina < BaseStat
377
+ attr_reader :health, :pet_bonus
378
+ def initialize(elem)
379
+ @base = elem[:base].to_i
380
+ @effective = elem[:effective].to_i
381
+ @health = elem[:health].to_i
382
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
383
+ end
384
+ end
385
+
386
+ class Intellect < BaseStat
387
+ attr_reader :mana, :crit_hit_percent, :pet_bonus
388
+ def initialize(elem)
389
+ @base = elem[:base].to_i
390
+ @effective = elem[:effective].to_i
391
+ @mana = elem[:mana].to_i
392
+ @crit_hit_percent = elem[:critHitPercent].to_f
393
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
394
+ end
395
+ end
396
+
397
+ class Spirit < BaseStat
398
+ attr_reader :health_regen, :mana_regen
399
+ def initialize(elem)
400
+ @base = elem[:base].to_i
401
+ @effective = elem[:effective].to_i
402
+ @health_regen = elem[:healthRegen].to_i
403
+ @mana_regen = elem[:manaRegen].to_i
404
+ end
405
+ end
406
+
407
+ class Armor < BaseStat
408
+ attr_reader :percent, :pet_bonus
409
+ def initialize(elem)
410
+ @base = elem[:base].to_i
411
+ @effective = elem[:effective].to_i
412
+ @percent = elem[:percent].to_f
413
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
414
+ end
415
+ end
416
+
417
+
418
+
419
+ # <melee>
420
+ # <mainHandDamage dps="65.6" max="149" min="60" percent="0" speed="1.60"/>
421
+ # <offHandDamage dps="0.0" max="0" min="0" percent="0" speed="2.00"/>
422
+ # <mainHandSpeed hastePercent="0.00" hasteRating="0" value="1.60"/>
423
+ # <offHandSpeed hastePercent="0.00" hasteRating="0" value="2.00"/>
424
+ # <power base="338" effective="338" increasedDps="24.0"/>
425
+ # <hitRating increasedHitPercent="0.00" value="0"/>
426
+ # <critChance percent="4.16" plusPercent="0.00" rating="0"/>
427
+ # <expertise additional="0" percent="0.00" rating="0" value="0"/>
428
+ # </melee>
429
+ class Melee
430
+ attr_reader :main_hand_skill, :off_hand_skill,
431
+ :main_hand_damage, :off_hand_damage,
432
+ :main_hand_speed, :off_hand_speed,
433
+ :power, :hit_rating, :crit_chance,
434
+ :expertise
435
+
436
+ def initialize(elem)
437
+ # TODO: Do these not exist anymore?
438
+ @main_hand_skill = WeaponSkill.new(elem%'mainHandWeaponSkill') if (elem%'mainHandWeaponSkill')
439
+ @off_hand_skill = WeaponSkill.new(elem%'offHandWeaponSkill') if (elem%'offHandWeaponSkill')
440
+
441
+ @main_hand_damage = WeaponDamage.new(elem%'mainHandDamage')
442
+ @off_hand_damage = WeaponDamage.new(elem%'offHandDamage')
443
+
444
+ @main_hand_speed = WeaponSpeed.new(elem%'mainHandSpeed')
445
+ @off_hand_speed = WeaponSpeed.new(elem%'offHandSpeed')
446
+
447
+ @power = WeaponPower.new(elem%'power')
448
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
449
+ @crit_chance = WeaponCritChance.new(elem%'critChance')
450
+
451
+ @expertise = WeaponExpertise.new(elem%'expertise')
452
+ end
453
+ end
454
+
455
+ # <ranged>
456
+ # <weaponSkill rating="0" value="-1"/>
457
+ # <damage dps="0.0" max="0" min="0" percent="0" speed="0.00"/>
458
+ # <speed hastePercent="0.00" hasteRating="0" value="0.00"/>
459
+ # <power base="57" effective="57" increasedDps="4.0" petAttack="-1.00" petSpell="-1.00"/>
460
+ # <hitRating increasedHitPercent="0.00" value="0"/>
461
+ # <critChance percent="0.92" plusPercent="0.00" rating="0"/>
462
+ # </ranged>
463
+ class Ranged
464
+ attr_reader :weapon_skill, :damage, :speed, :power,
465
+ :hit_rating, :crit_chance
466
+
467
+ def initialize(elem)
468
+ @weapon_skill = WeaponSkill.new(elem%'weaponSkill')
469
+ @damage = WeaponDamage.new(elem%'damage')
470
+ @speed = WeaponSpeed.new(elem%'speed')
471
+ @power = WeaponPower.new(elem%'power')
472
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
473
+ @crit_chance = WeaponCritChance.new(elem%'critChance')
474
+ end
475
+ end
476
+
477
+ class WeaponSkill
478
+ attr_reader :rating, :value
479
+
480
+ def initialize(elem)
481
+ @value = elem[:value].to_i == -1 ? nil : elem[:value].to_i
482
+ @rating = elem[:rating].to_i
483
+ end
484
+ end
485
+
486
+ class WeaponDamage
487
+ attr_reader :dps, :max, :min, :percent, :speed
488
+
489
+ def initialize(elem)
490
+ @dps = elem[:dps].to_f
491
+ @max = elem[:max].to_i
492
+ @min = elem[:min].to_i
493
+ @percent = elem[:percent].to_f
494
+ @speed = elem[:speed].to_f
495
+ end
496
+ end
497
+
498
+ class WeaponSpeed
499
+ attr_reader :haste_percent, :haste_rating, :value
500
+
501
+ def initialize(elem)
502
+ @haste_percent = elem[:hastePercent].to_f
503
+ @haste_rating = elem[:hasteRating].to_f
504
+ @value = elem[:value].to_f
505
+ end
506
+ end
507
+
508
+ class WeaponPower
509
+ attr_reader :base, :effective, :increased_dps, :pet_attack, :pet_spell, :haste_rating
510
+
511
+ def initialize(elem)
512
+ @base = elem[:base].to_i
513
+ @haste_rating = elem[:effective].to_i
514
+ @increased_dps = elem[:increasedDps].to_f
515
+ @pet_attack = (elem[:petAttack].to_f == -1 ? nil : elem[:petAttack].to_f)
516
+ @pet_spell = (elem[:petSpell].to_f == -1 ? nil : elem[:petSpell].to_f)
517
+ end
518
+ end
519
+
520
+ class WeaponHitRating
521
+ attr_reader :increased_hit_percent, :value
522
+
523
+ def initialize(elem)
524
+ @increased_hit_percent = elem[:increasedHitPercent].to_f
525
+ @value = elem[:value].to_f
526
+ end
527
+ end
528
+
529
+ class WeaponCritChance
530
+ attr_reader :percent, :plus_percent, :rating
531
+
532
+ def initialize(elem)
533
+ @percent = elem[:percent].to_f
534
+ @plus_percent = elem[:plusPercent].to_f
535
+ @rating = elem[:rating].to_i
536
+ end
537
+ end
538
+
539
+ # <expertise additional="0" percent="0.00" rating="0" value="0"/>
540
+ class WeaponExpertise
541
+ attr_reader :additional, :percent, :rating, :value
542
+
543
+ def initialize(elem)
544
+ @additional = elem[:additional].to_i
545
+ @percent = elem[:percent].to_f
546
+ @rating = elem[:rating].to_i
547
+ @value = elem[:value].to_i
548
+ end
549
+ end
550
+
551
+
552
+ # Decided to do funky stuff to the XML to make it more useful.
553
+ # instead of having two seperate lists of bonusDamage and critChance
554
+ # merged it into one set of objects for each thing
555
+ class Spell
556
+ attr_reader :arcane, :fire, :frost, :holy, :nature, :shadow,
557
+ :hit_rating, :bonus_healing, :penetration, :mana_regen, :speed
558
+
559
+ def initialize(elem)
560
+ @arcane = SpellDamage.new(elem%'bonusDamage'%'arcane', elem%'critChance'%'arcane')
561
+ @fire = SpellDamage.new(elem%'bonusDamage'%'fire', elem%'critChance'%'fire')
562
+ @frost = SpellDamage.new(elem%'bonusDamage'%'frost', elem%'critChance'%'frost')
563
+ @holy = SpellDamage.new(elem%'bonusDamage'%'holy', elem%'critChance'%'holy')
564
+ @nature = SpellDamage.new(elem%'bonusDamage'%'nature', elem%'critChance'%'nature')
565
+ @shadow = SpellDamage.new(elem%'bonusDamage'%'shadow', elem%'critChance'%'shadow')
566
+
567
+ @bonus_healing = (elem%'bonusHealing')[:value].to_i # is this right??
568
+ @penetration = (elem%'penetration')[:value].to_i
569
+ @hit_rating = WeaponHitRating.new(elem%'hitRating')
570
+ @mana_regen = ManaRegen.new(elem%'manaRegen')
571
+ @speed = SpellSpeed.new(elem%'hasteRating')
572
+
573
+ # elements = %w[arcane fire frost holy nature shadow]
574
+ # elements.each do |element|
575
+ # # TODO: is this a good idea?
576
+ # #instance_variable_set("@#{element}", foo) #??
577
+ # #eval("@#{element} = SpellDamage.new(elem[:bonusDamage][element][:value], elem[:critChance][element][:percent]).to_f)")
578
+ # # eval("@#{element} = SpellDamage.new((elem%'bonusDamage'%element)[:value].to_i,
579
+ # # (elem%'critChance'%element)[:percent].to_f)")
580
+ # end
581
+ end
582
+ end
583
+
584
+ class SpellSpeed
585
+ attr_reader :percent_increase, :haste_rating
586
+
587
+ def initialize(elem)
588
+ @percent_increase = elem[:hastePercent].to_f
589
+ @haste_rating = elem[:hasteRating].to_i
590
+ end
591
+ end
592
+
593
+ class SpellDamage
594
+ attr_reader :value, :crit_chance_percent
595
+ alias_method :percent, :crit_chance_percent
596
+
597
+ def initialize(bonusDamage_elem, critChance_elem)
598
+ @value = bonusDamage_elem[:value].to_i
599
+ @crit_chance_percent = critChance_elem[:percent].to_f
600
+ end
601
+ end
602
+
603
+ class ManaRegen
604
+ attr_reader :casting, :not_casting
605
+
606
+ def initialize(elem)
607
+ @casting = elem[:casting].to_f
608
+ @not_casting = elem[:notCasting].to_f
609
+ end
610
+ end
611
+
612
+ class PetBonus
613
+ attr_reader :attack, :damage, :from_Type
614
+
615
+ def initialize(elem)
616
+ @attack = elem[:attack].to_i == -1 ? nil : elem[:attack].to_i
617
+ @damage = elem[:damage].to_i == -1 ? nil : elem[:damage].to_i
618
+ @from_type = elem[:fromType] if elem[:fromType]
619
+ end
620
+ end
621
+
622
+
623
+
624
+ class Defenses
625
+ attr_reader :armor, :defense, :dodge, :parry, :block, :resilience
626
+
627
+ def initialize(elem)
628
+ @armor = Armor.new(elem%'armor')
629
+ @defense = Defense.new(elem%'defense')
630
+ @dodge = DodgeParryBlock.new(elem%'dodge')
631
+ @parry = DodgeParryBlock.new(elem%'parry')
632
+ @block = DodgeParryBlock.new(elem%'block')
633
+ @resilience = Resilience.new(elem%'resilience')
634
+ end
635
+ end
636
+
637
+ class Armor
638
+ attr_reader :base, :effective, :percent, :pet_bonus
639
+
640
+ def initialize(elem)
641
+ @base = elem[:base].to_i
642
+ @effective = elem[:effective].to_i
643
+ @percent = elem[:percent].to_f
644
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
645
+ end
646
+ end
647
+
648
+ class Defense
649
+ attr_reader :value, :increase_percent, :decrease_percent, :plus_defense, :rating
650
+
651
+ def initialize(elem)
652
+ @value = elem[:value].to_i
653
+ @increase_percent = elem[:increasePercent].to_f
654
+ @decrease_percent = elem[:decreasePercent].to_f
655
+ @plus_defense = elem[:plusDefense].to_i
656
+ @rating = elem[:rating].to_i
657
+ end
658
+ end
659
+
660
+ class DodgeParryBlock
661
+ attr_reader :percent, :increase_percent, :rating
662
+
663
+ def initialize(elem)
664
+ @percent = elem[:percent].to_f
665
+ @increase_percent = elem[:increasePercent].to_f
666
+ @rating = elem[:rating].to_i
667
+ end
668
+ end
669
+
670
+ class Resilience
671
+ attr_reader :damage_percent, :hit_percent, :value
672
+
673
+ def initialize(elem)
674
+ @damage_percent = elem[:damagePercent].to_f
675
+ @hit_percent = elem[:hitPercent].to_f
676
+ @value = elem[:value].to_f
677
+ end
678
+ end
679
+
680
+
681
+ class Resistance
682
+ attr_reader :value, :pet_bonus
683
+
684
+ def initialize(elem)
685
+ @value = elem[:value].to_i
686
+ @pet_bonus = elem[:petBonus].to_i == -1 ? nil : elem[:petBonus].to_i
687
+ end
688
+ end
689
+
690
+
691
+ # Note the list of talent trees starts at 1. This is quirky, but that's what's used in the XML
692
+ class TalentSpec
693
+ attr_reader :trees, :active, :group, :primary
694
+
695
+ def initialize(elem)
696
+ @trees = []
697
+ @trees[1] = elem[:treeOne].to_i
698
+ @trees[2] = elem[:treeTwo].to_i
699
+ @trees[3] = elem[:treeThree].to_i
700
+ @active = (elem[:active].to_i == 1 ? true : false)
701
+ @group = elem[:group].to_i
702
+ @primary = elem[:prim]
703
+ end
704
+ end
705
+
706
+
707
+ # Player-versus-player data
708
+ class Pvp
709
+ attr_reader :lifetime_honorable_kills, :arena_currency
710
+
711
+ def initialize(elem)
712
+ @lifetime_honorable_kills = (elem%'lifetimehonorablekills')[:value].to_i
713
+ @arena_currency = (elem%'arenacurrency')[:value].to_i
714
+ end
715
+ end
716
+
717
+
718
+ # A buff
719
+ # TODO: Code duplication, see basic Item class. Make extend Icon class?
720
+ class Buff
721
+ attr_reader :name, :effect, :icon_base
722
+ alias_method :to_s, :name
723
+
724
+ @@icon_url_base = 'images/icons/'
725
+ @@icon_sizes = {:large => ['64x64', 'jpg'], :medium => ['43x43', 'png'], :small => ['21x21', 'png']}
726
+
727
+ def initialize(elem, api = nil)
728
+ @api = api
729
+
730
+ @name = elem[:name]
731
+ @effect = elem[:effect]
732
+ @icon_base = elem[:icon]
733
+ end
734
+
735
+ # http://armory.worldofwarcraft.com/images/icons/21x21/spell_holy_arcaneintellect.png
736
+ def icon(size = :medium)
737
+ if !@@icon_sizes.include?(size)
738
+ raise Wowr::Exceptions::InvalidIconSize.new(@@icon_sizes)
739
+ end
740
+
741
+ if @api
742
+ base = @api.base_url
743
+ else
744
+ base = 'http://www.wowarmory.com/'
745
+ end
746
+
747
+ # http://www.wowarmory.com/images/icons/64x64/blahblah.jpg
748
+ return base + @@icon_url_base + @@icon_sizes[size][0] + '/' + @icon_base + '.' + @@icon_sizes[size][1]
749
+ end
750
+ end
751
+
752
+
753
+ # An item equipped to a player
754
+ class EquippedItem < Item
755
+ attr_reader :durability, :max_durability, #:id, :item_id, :icon,
756
+ :gems, :permanent_enchant,
757
+ :random_properties_id, :seed, :slot
758
+
759
+ def initialize(elem, api = nil)
760
+ super(elem, api)
761
+ @durability = elem[:durability].to_i
762
+ @max_durability = elem[:maxDurability].to_i
763
+ @gems = []
764
+ @gems[0] = elem[:gem0Id].to_i == 0 ? nil : elem[:gem0Id].to_i
765
+ @gems[1] = elem[:gem1Id].to_i == 0 ? nil : elem[:gem1Id].to_i
766
+ @gems[2] = elem[:gem2Id].to_i == 0 ? nil : elem[:gem2Id].to_i
767
+ @permanent_enchant = elem[:permanentenchant].to_i
768
+ @random_properties_id = elem[:randomPropertiesId] == 0 ? nil : elem[:randomPropertiesId].to_i
769
+ @seed = elem[:seed].to_i # not sure if seed is so big it's overloading
770
+ @slot = elem[:slot].to_i
771
+ end
772
+ end
773
+
774
+
775
+ # eg Daggers, Riding, Fishing, language
776
+ class Skill
777
+ attr_reader :key, :name, :value, :max
778
+ alias_method :to_s, :name
779
+ alias_method :to_i, :value
780
+
781
+ def initialize(elem)
782
+ @key = elem[:key]
783
+ @name = elem[:name]
784
+ @value = elem[:value].to_i
785
+ @max = elem[:max].to_i
786
+ end
787
+ end
788
+
789
+
790
+ # Larger group of factions
791
+ # Used for faction information
792
+ # eg Alliance, Shattrath City, Steamwheedle Cartel
793
+ class RepFactionCategory
794
+ attr_reader :key, :name, :factions
795
+ alias_method :to_s, :name
796
+
797
+ def initialize(elem)
798
+ @key = elem[:key]
799
+ @name = elem[:name]
800
+
801
+ @factions = {}
802
+ (elem/:faction).each do |faction|
803
+ @factions[faction[:key]] = RepFaction.new(faction)
804
+ end
805
+ end
806
+
807
+ def total
808
+ total = 0
809
+ factions.each_value { |faction| total += faction.reputation }
810
+ return total
811
+ end
812
+ end
813
+
814
+
815
+ # Smaller NPC faction that is part of a FactionCategory
816
+ # eg Darnassus, Argent Dawn
817
+ class RepFaction
818
+ attr_reader :key, :name, :reputation
819
+ alias_method :to_s, :name
820
+ alias_method :to_i, :reputation
821
+
822
+ alias_method :rep, :reputation
823
+
824
+ def initialize(elem)
825
+ @key = elem[:key]
826
+ @name = elem[:name]
827
+ @reputation = elem[:reputation].to_i
828
+ end
829
+ end
830
+
831
+ end
832
+ end