steam-condenser 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +2 -0
  3. data/Rakefile +0 -2
  4. data/VERSION.yml +1 -1
  5. data/lib/abstract_class.rb +1 -3
  6. data/lib/exceptions/buffer_underflow_exception.rb +1 -3
  7. data/lib/exceptions/packet_format_exception.rb +1 -3
  8. data/lib/exceptions/rcon_no_auth_exception.rb +1 -3
  9. data/lib/exceptions/timeout_exception.rb +0 -2
  10. data/lib/steam/community/game_stats.rb +5 -3
  11. data/lib/steam/community/l4d/abstract_l4d_stats.rb +143 -0
  12. data/lib/steam/community/l4d/abstract_l4d_weapon.rb +26 -0
  13. data/lib/steam/community/l4d/l4d2_map.rb +65 -0
  14. data/lib/steam/community/l4d/l4d2_stats.rb +125 -0
  15. data/lib/steam/community/l4d/l4d2_weapon.rb +21 -0
  16. data/lib/steam/community/l4d/l4d_map.rb +2 -0
  17. data/lib/steam/community/l4d/l4d_stats.rb +5 -115
  18. data/lib/steam/community/l4d/l4d_weapon.rb +3 -7
  19. data/lib/steam/community/steam_id.rb +28 -19
  20. data/lib/steam/community/tf2/tf2_class_factory.rb +1 -3
  21. data/lib/steam/community/tf2/tf2_engineer.rb +2 -4
  22. data/lib/steam/community/tf2/tf2_medic.rb +1 -3
  23. data/lib/steam/community/tf2/tf2_sniper.rb +1 -3
  24. data/lib/steam/community/tf2/tf2_spy.rb +1 -3
  25. data/lib/steam/packets/a2a_ack_packet.rb +1 -3
  26. data/lib/steam/packets/a2a_ping_packet.rb +1 -3
  27. data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +0 -2
  28. data/lib/steam/packets/a2s_info_packet.rb +0 -2
  29. data/lib/steam/packets/a2s_player_packet.rb +1 -3
  30. data/lib/steam/packets/a2s_rules_packet.rb +1 -3
  31. data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +1 -3
  32. data/lib/steam/packets/m2a_server_batch_packet.rb +1 -3
  33. data/lib/steam/packets/rcon/rcon_auth_request.rb +1 -3
  34. data/lib/steam/packets/rcon/rcon_auth_response.rb +1 -3
  35. data/lib/steam/packets/rcon/rcon_exec_request.rb +1 -3
  36. data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +1 -3
  37. data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +1 -3
  38. data/lib/steam/packets/rcon/rcon_packet.rb +1 -3
  39. data/lib/steam/packets/rcon/rcon_packet_factory.rb +1 -3
  40. data/lib/steam/packets/request_with_challenge.rb +1 -3
  41. data/lib/steam/packets/s2a_info2_packet.rb +1 -3
  42. data/lib/steam/packets/s2a_info_base_packet.rb +2 -0
  43. data/lib/steam/packets/s2a_rules_packet.rb +1 -1
  44. data/lib/steam/packets/s2c_challenge_packet.rb +1 -3
  45. data/lib/steam/packets/steam_packet.rb +15 -16
  46. data/lib/steam/servers/master_server.rb +0 -2
  47. data/lib/steam/servers/source_server.rb +3 -1
  48. data/lib/steam-condenser.rb +2 -0
  49. metadata +21 -19
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008, Sebastian Staudt
1
+ Copyright (c) 2008-2009, Sebastian Staudt
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
data/README.md CHANGED
@@ -28,3 +28,5 @@ file.
28
28
  * [GitHub project page](http://github.com/koraktor/steam-condenser)
29
29
  * [Google group](http://groups.google.com/group/steam-condenser)
30
30
  * [Ohloh profile](http://www.ohloh.net/projects/steam-condenser)
31
+
32
+ Follow Steam Condenser on Twitter [@steamcondenser](http://twitter.com/steamcondenser).
data/Rakefile CHANGED
@@ -23,8 +23,6 @@ Jeweler::Tasks.new do |s|
23
23
 
24
24
  s.files = %w(README.md Rakefile LICENSE VERSION.yml) + src_files + test_files
25
25
  s.rdoc_options = ["--all", "--inline-source", "--line-numbers", "--charset=utf-8", "--webcvs=http://github.com/koraktor/steam-condenser/source/blob/master/ruby/%s"]
26
-
27
- s.add_dependency('hpricot', '>= 0.6')
28
26
  end
29
27
 
30
28
  # Create a rake task +:rdoc+ to build the documentation
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 9
3
+ :minor: 10
4
4
  :patch: 0
@@ -1,9 +1,7 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008, Sebastian Staudt
5
- #
6
- # $Id$
4
+ # Copyright (c) 2008-2009, Sebastian Staudt
7
5
 
8
6
  # This module is used to mimic the behavior of abstract classes known from other
9
7
  # object-oriented programming languages
@@ -1,9 +1,7 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008, Sebastian Staudt
5
- #
6
- # $Id$
4
+ # Copyright (c) 2008-2009, Sebastian Staudt
7
5
 
8
6
  class BufferUnderflowException < Exception
9
7
 
@@ -1,9 +1,7 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008, Sebastian Staudt
5
- #
6
- # $Id$
4
+ # Copyright (c) 2008-2009, Sebastian Staudt
7
5
 
8
6
  require "exceptions/steam_condenser_exception"
9
7
 
@@ -1,9 +1,7 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008, Sebastian Staudt
5
- #
6
- # $Id$
4
+ # Copyright (c) 2008-2009, Sebastian Staudt
7
5
 
8
6
  class RCONNoAuthException < Exception
9
7
 
@@ -2,8 +2,6 @@
2
2
  # terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2009, Sebastian Staudt
5
- #
6
- # $Id$
7
5
 
8
6
  class TimeoutException < StandardError
9
7
 
@@ -14,6 +14,7 @@ end
14
14
  require 'steam/community/defense_grid/defense_grid_stats'
15
15
  require "steam/community/dods/dods_stats"
16
16
  require "steam/community/l4d/l4d_stats"
17
+ require "steam/community/l4d/l4d2_stats"
17
18
  require "steam/community/tf2/tf2_stats"
18
19
 
19
20
  # The GameStats class represents the game statistics for a single user and a
@@ -35,6 +36,8 @@ class GameStats
35
36
  DoDSStats.new(steam_id)
36
37
  when 'l4d'
37
38
  L4DStats.new(steam_id)
39
+ when 'l4d2'
40
+ L4D2Stats.new(steam_id)
38
41
  when 'tf2'
39
42
  TF2Stats.new(steam_id)
40
43
  else
@@ -42,8 +45,8 @@ class GameStats
42
45
  end
43
46
  end
44
47
 
45
- # Creates a GameStats object and fetchs data from Steam Community for the
46
- # given user and game
48
+ # Creates a GameStats object and fetches data from the Steam Community for
49
+ # the given user and game
47
50
  def initialize(id, game_name)
48
51
  if id.is_a? Numeric
49
52
  @steam_id64 = id
@@ -58,7 +61,6 @@ class GameStats
58
61
  @privacy_state = @xml_data.elements['privacyState'].text
59
62
  if public?
60
63
  @app_id = @xml_data.elements['game/gameLink'].text.match(/http:\/\/store.steampowered.com\/app\/([1-9][0-9]+)/)[1]
61
- @game_friendly_name = @xml_data.elements['game/gameFriendlyName'].text
62
64
  @game_name = @xml_data.elements['game/gameName'].text
63
65
  @hours_played = @xml_data.elements['stats/hoursPlayed'].text
64
66
  end
@@ -0,0 +1,143 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2009, Sebastian Staudt
5
+
6
+ require 'abstract_class'
7
+ require 'steam/community/game_stats'
8
+
9
+ # AbstractL4DStats is an abstract base class for statistics for Left4Dead and
10
+ # Left4Dead 2. As both games have more or less the same statistics available in
11
+ # the Steam Community the code for both is pretty much the same.
12
+ class AbstractL4DStats < GameStats
13
+
14
+ include AbstractClass
15
+
16
+ SPECIAL_INFECTED = %w(boomer hunter smoker tank)
17
+
18
+ def initialize(steam_id, game_name)
19
+ super steam_id, game_name
20
+
21
+ if public?
22
+ @most_recent_game = {}
23
+ if @xml_data.elements['stats/mostrecentgame'].has_elements?
24
+ @most_recent_game['difficulty'] = @xml_data.elements['stats/mostrecentgame/difficulty'].text
25
+ @most_recent_game['escaped'] = (@xml_data.elements['stats/mostrecentgame/bEscaped'].text == 1)
26
+ @most_recent_game['movie'] = @xml_data.elements['stats/mostrecentgame/movie'].text
27
+ @most_recent_game['time_played'] = @xml_data.elements['stats/mostrecentgame/time'].text
28
+ end
29
+ end
30
+ end
31
+
32
+ # Returns a Hash of favorites for this user like weapons and character.
33
+ # If the favorites haven't been parsed already, parsing is done now.
34
+ def favorites
35
+ return unless public?
36
+
37
+ if @favorites.nil?
38
+ @favorites = {}
39
+ @favorites['campaign'] = @xml_data.elements['stats/favorites/campaign'].text
40
+ @favorites['campaign_percentage'] = @xml_data.elements['stats/favorites/campaignpct'].text.to_i
41
+ @favorites['character'] = @xml_data.elements['stats/favorites/character'].text
42
+ @favorites['character_percentage'] = @xml_data.elements['stats/favorites/characterpct'].text.to_i
43
+ @favorites['level1_weapon'] = @xml_data.elements['stats/favorites/weapon1'].text
44
+ @favorites['level1_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon1pct'].text.to_i
45
+ @favorites['level2_weapon'] = @xml_data.elements['stats/favorites/weapon2'].text
46
+ @favorites['level2_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon2pct'].text.to_i
47
+ end
48
+
49
+ @favorites
50
+ end
51
+
52
+ # Returns a Hash of lifetime statistics for this user like the time played.
53
+ # If the lifetime statistics haven't been parsed already, parsing is done now.
54
+ def lifetime_stats
55
+ return unless public?
56
+
57
+ if @lifetime_stats.nil?
58
+ @lifetime_stats = {}
59
+ @lifetime_stats['finales_survived'] = @xml_data.elements['stats/lifetime/finales'].text.to_i
60
+ @lifetime_stats['games_played'] = @xml_data.elements['stats/lifetime/gamesplayed'].text.to_i
61
+ @lifetime_stats['finales_survived_percentage'] = @lifetime_stats['finales_survived'].to_f / @lifetime_stats['games_played']
62
+ @lifetime_stats['infected_killed'] = @xml_data.elements['stats/lifetime/infectedkilled'].text.to_i
63
+ @lifetime_stats['kills_per_hour'] = @xml_data.elements['stats/lifetime/killsperhour'].text.to_f
64
+ @lifetime_stats['avg_kits_shared'] = @xml_data.elements['stats/lifetime/kitsshared'].text.to_f
65
+ @lifetime_stats['avg_kits_used'] = @xml_data.elements['stats/lifetime/kitsused'].text.to_f
66
+ @lifetime_stats['avg_pills_shared'] = @xml_data.elements['stats/lifetime/pillsshared'].text.to_f
67
+ @lifetime_stats['avg_pills_used'] = @xml_data.elements['stats/lifetime/pillsused'].text.to_f
68
+ @lifetime_stats['time_played'] = @xml_data.elements['stats/lifetime/timeplayed'].text
69
+ end
70
+
71
+ @lifetime_stats
72
+ end
73
+
74
+ # Returns a Hash of Survival statistics for this user like revived teammates.
75
+ # If the Survival statistics haven't been parsed already, parsing is done now.
76
+ def survival_stats
77
+ return unless public?
78
+
79
+ if @survival_stats.nil?
80
+ @survival_stats = {}
81
+ @survival_stats['gold_medals'] = @xml_data.elements['stats/survival/goldmedals'].text.to_i
82
+ @survival_stats['silver_medals'] = @xml_data.elements['stats/survival/silvermedals'].text.to_i
83
+ @survival_stats['bronze_medals'] = @xml_data.elements['stats/survival/bronzemedals'].text.to_i
84
+ @survival_stats['rounds_played'] = @xml_data.elements['stats/survival/roundsplayed'].text.to_i
85
+ @survival_stats['best_time'] = @xml_data.elements['stats/survival/besttime'].text.to_f
86
+ end
87
+
88
+ @survival_stats
89
+ end
90
+
91
+ # Returns a Hash of teamplay statistics for this user like revived teammates.
92
+ # If the teamplay statistics haven't been parsed already, parsing is done now.
93
+ def teamplay_stats
94
+ return unless public?
95
+
96
+ if @teamplay_stats.nil?
97
+ @teamplay_stats = {}
98
+ @teamplay_stats['revived'] = @xml_data.elements['stats/teamplay/revived'].text.to_i
99
+ @teamplay_stats['most_revived_difficulty'] = @xml_data.elements['stats/teamplay/reviveddiff'].text
100
+ @teamplay_stats['avg_revived'] = @xml_data.elements['stats/teamplay/revivedavg'].text.to_f
101
+ @teamplay_stats['avg_was_revived'] = @xml_data.elements['stats/teamplay/wasrevivedavg'].text.to_f
102
+ @teamplay_stats['protected'] = @xml_data.elements['stats/teamplay/protected'].text.to_i
103
+ @teamplay_stats['most_protected_difficulty'] = @xml_data.elements['stats/teamplay/protecteddiff'].text
104
+ @teamplay_stats['avg_protected'] = @xml_data.elements['stats/teamplay/protectedavg'].text.to_f
105
+ @teamplay_stats['avg_was_protected'] = @xml_data.elements['stats/teamplay/wasprotectedavg'].text.to_f
106
+ @teamplay_stats['friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamage'].text.to_i
107
+ @teamplay_stats['most_friendly_fire_difficulty'] = @xml_data.elements['stats/teamplay/ffdamagediff'].text
108
+ @teamplay_stats['avg_friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamageavg'].text.to_f
109
+ end
110
+
111
+ @teamplay_stats
112
+ end
113
+
114
+ # Returns a Hash of Versus statistics for this user like percentage of rounds
115
+ # won.
116
+ # If the Versus statistics haven't been parsed already, parsing is done now.
117
+ def versus_stats
118
+ return unless public?
119
+
120
+ if @versus_stats.nil?
121
+ @versus_stats = {}
122
+ @versus_stats['games_played'] = @xml_data.elements['stats/versus/gamesplayed'].text.to_i
123
+ @versus_stats['games_completed'] = @xml_data.elements['stats/versus/gamescompleted'].text.to_i
124
+ @versus_stats['finales_survived'] = @xml_data.elements['stats/versus/finales'].text.to_i
125
+ @versus_stats['finales_survived_percentage'] = @versus_stats['finales_survived'].to_f / @versus_stats['games_played']
126
+ @versus_stats['points'] = @xml_data.elements['stats/versus/points'].text.to_i
127
+ @versus_stats['most_points_infected'] = @xml_data.elements['stats/versus/pointsas'].text
128
+ @versus_stats['games_won'] = @xml_data.elements['stats/versus/gameswon'].text.to_i
129
+ @versus_stats['games_lost'] = @xml_data.elements['stats/versus/gameslost'].text.to_i
130
+ @versus_stats['highest_survivor_score'] = @xml_data.elements['stats/versus/survivorscore'].text.to_i
131
+
132
+ self.class.const_get(:SPECIAL_INFECTED).each do |infected|
133
+ @versus_stats[infected] = {}
134
+ @versus_stats[infected]['special_attacks'] = @xml_data.elements["stats/versus/#{infected}special"].text.to_i
135
+ @versus_stats[infected]['most_damage'] = @xml_data.elements["stats/versus/#{infected}dmg"].text.to_i
136
+ @versus_stats[infected]['avg_lifespan'] = @xml_data.elements["stats/versus/#{infected}lifespan"].text.to_i
137
+ end
138
+ end
139
+
140
+ @versus_stats
141
+ end
142
+
143
+ end
@@ -0,0 +1,26 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2009-2010, Sebastian Staudt
5
+
6
+ require 'abstract_class'
7
+ require 'steam/community/game_weapon'
8
+
9
+ class AbstractL4DWeapon < GameWeapon
10
+
11
+ include AbstractClass
12
+
13
+ attr_reader :accuracy, :headshots_percentage, :kill_percentage
14
+
15
+ # Abstract base constructor which parses common data for both, L4DWeapon and
16
+ # L4D2Weapon
17
+ def initialize(weapon_data)
18
+ super weapon_data
19
+
20
+ @accuracy = weapon_data.elements['accuracy'].text
21
+ @headshots_percentage = weapon_data.elements['headshots'].text
22
+ @id = weapon_data.name
23
+ @shots = weapon_data.elements['shots'].text.to_i
24
+ end
25
+
26
+ end
@@ -0,0 +1,65 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2009-2010, Sebastian Staudt
5
+
6
+ require 'steam/community/steam_id'
7
+ require 'steam/community/l4d/l4d_map'
8
+
9
+ # L4D2Map holds statistical information about maps played by a player in
10
+ # Survival mode of Left4Dead 2. The basic information provided is more or less
11
+ # the same for Left4Dead and Left4Dead 2, but parsing has to be done
12
+ # differently.
13
+ class L4D2Map < L4DMap
14
+
15
+ attr_reader :items, :kills, :teammates
16
+
17
+ INFECTED = %w{boomer charger common hunter jockey smoker spitter tank}
18
+ ITEMS = %w{adrenaline defibs medkits pills}
19
+
20
+ # Creates a new instance of L4D2Map based on the assigned XML data
21
+ #
22
+ # The map statistics for the Survival mode of Left4Dead 2 hold much more
23
+ # information than those for Left4Dead, e.g. the teammates and items are
24
+ # listed.
25
+ def initialize(map_data)
26
+ @id = map_data.elements['img'].text.match(/http:\/\/steamcommunity\.com\/public\/images\/gamestats\/550\/(.*).jpg/)[1]
27
+ @name = map_data.elements['name'].text
28
+ @played = (map_data.elements['hasPlayed'].text.to_i == 1)
29
+
30
+ if @played
31
+ @best_time = map_data.elements['besttimemilliseconds'].text.to_f / 1000
32
+
33
+ @teammates = []
34
+ map_data.elements.each('teammates/steamID64') do |teammate|
35
+ @teammates << SteamId.new(teammate.text, false)
36
+ end
37
+
38
+ @items = {}
39
+ ITEMS.each do |item|
40
+ @items[item] = map_data.elements["items_#{item}"].text.to_i
41
+ end
42
+
43
+ @kills = {}
44
+ INFECTED.each do |infected|
45
+ @kills[infected] = map_data.elements["kills_#{infected}"].text.to_i
46
+ end
47
+
48
+ case map_data.elements['medal'].text
49
+ when 'gold'
50
+ @medal = L4D2Map::GOLD
51
+ when 'silver'
52
+ @medal = L4D2Map::SILVER
53
+ when 'bronze'
54
+ @medal = L4D2Map::BRONZE
55
+ else
56
+ @medal = L4D2Map::NONE
57
+ end
58
+ end
59
+ end
60
+
61
+ def played?
62
+ @played
63
+ end
64
+
65
+ end
@@ -0,0 +1,125 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2009-2010, Sebastian Staudt
5
+
6
+ require 'steam/community/l4d/abstract_l4d_stats'
7
+ require 'steam/community/l4d/l4d2_map'
8
+ require 'steam/community/l4d/l4d2_weapon'
9
+
10
+ class L4D2Stats < AbstractL4DStats
11
+
12
+ SPECIAL_INFECTED = SPECIAL_INFECTED + %w{charger jockey spitter}
13
+
14
+ # Creates a L4D2Stats object by calling the super constructor with the game
15
+ # name "l4d2"
16
+ def initialize(steam_id)
17
+ super steam_id, 'l4d2'
18
+ end
19
+
20
+ # Returns a Hash of lifetime statistics for this user like the time played.
21
+ # If the lifetime statistics haven't been parsed already, parsing is done now.
22
+ #
23
+ # There are only a few additional lifetime statistics for Left4Dead 2 which
24
+ # are not generated for Left4Dead, so this calls
25
+ # AbstractL4DStats#lifetime_stats first and adds some additional stats.
26
+ def lifetime_stats
27
+ return unless public?
28
+
29
+ if @lifetime_stats.nil?
30
+ super
31
+ @lifetime_stats['avg_adrenaline_shared'] = @xml_data.elements['stats/lifetime/adrenalineshared'].text.to_f
32
+ @lifetime_stats['avg_adrenaline_used'] = @xml_data.elements['stats/lifetime/adrenalineused'].text.to_f
33
+ @lifetime_stats['avg_defibrillators_used'] = @xml_data.elements['stats/lifetime/defibrillatorsused'].text.to_f
34
+ end
35
+
36
+ @lifetime_stats
37
+ end
38
+
39
+ # Returns a Hash of Scavenge statistics for this user like the number of
40
+ # Scavenge rounds played.
41
+ # If the Scavenge statistics haven't been parsed already, parsing is done now.
42
+ def scavenge_stats
43
+ return unless public?
44
+
45
+ if @scavenge_stats.nil?
46
+ @scavenge_stats = {}
47
+ @scavenge_stats['avg_cans_per_round'] = @xml_data.elements['stats/scavenge/avgcansperround'].text.to_f
48
+ @scavenge_stats['perfect_rounds'] = @xml_data.elements['stats/scavenge/perfect16canrounds'].text.to_i
49
+ @scavenge_stats['rounds_lost'] = @xml_data.elements['stats/scavenge/roundslost'].text.to_i
50
+ @scavenge_stats['rounds_played'] = @xml_data.elements['stats/scavenge/roundsplayed'].text.to_i
51
+ @scavenge_stats['rounds_won'] = @xml_data.elements['stats/scavenge/roundswon'].text.to_i
52
+ @scavenge_stats['total_cans'] = @xml_data.elements['stats/scavenge/totalcans'].text.to_i
53
+
54
+ @scavenge_stats['maps'] = {}
55
+ @xml_data.elements.each('stats/scavenge/mapstats/map') do |map_data|
56
+ map_id = map_data.elements['name'].text
57
+ @scavenge_stats['maps'][map_id] = {}
58
+ @scavenge_stats['maps'][map_id]['avg_round_score'] = map_data.elements['avgscoreperround'].text.to_i
59
+ @scavenge_stats['maps'][map_id]['highest_game_score'] = map_data.elements['highgamescore'].text.to_i
60
+ @scavenge_stats['maps'][map_id]['highest_round_score'] = map_data.elements['highroundscore'].text.to_i
61
+ @scavenge_stats['maps'][map_id]['name'] = map_data.elements['fullname'].text
62
+ @scavenge_stats['maps'][map_id]['rounds_played'] = map_data.elements['roundsplayed'].text.to_i
63
+ @scavenge_stats['maps'][map_id]['rounds_won'] = map_data.elements['roundswon'].text.to_i
64
+ end
65
+
66
+ @scavenge_stats['infected'] = {}
67
+ @xml_data.elements.each('stats/scavenge/infectedstats/special') do |infected_data|
68
+ infected_id = infected_data.elements['name'].text
69
+ @scavenge_stats['infected'][infected_id] = {}
70
+ @scavenge_stats['infected'][infected_id]['max_damage_per_life'] = infected_data.elements['maxdmg1life'].text.to_i
71
+ @scavenge_stats['infected'][infected_id]['max_pours_interrupted'] = infected_data.elements['maxpoursinterrupted'].text.to_i
72
+ @scavenge_stats['infected'][infected_id]['special_attacks'] = infected_data.elements['specialattacks'].text.to_i
73
+ end
74
+ end
75
+
76
+ @scavenge_stats
77
+ end
78
+
79
+ # Returns a Hash of Survival statistics for this user like revived teammates.
80
+ # If the Survival statistics haven't been parsed already, parsing is done now.
81
+ #
82
+ # The XML layout for the Survival statistics for Left4Dead 2 differs a bit
83
+ # from Left4Dead's Survival statistics. So we have to use a different way of
84
+ # parsing for the maps and we use a different map class (L4D2Map) which holds
85
+ # the additional information provided in Left4Dead 2's statistics.
86
+ def survival_stats
87
+ return unless public?
88
+
89
+ if @survival_stats.nil?
90
+ super
91
+ @survival_stats['maps'] = {}
92
+ @xml_data.elements.each('stats/survival/maps/map') do |map_data|
93
+ map = L4D2Map.new(map_data)
94
+ @survival_stats['maps'][map.id] = map
95
+ end
96
+ end
97
+
98
+ @survival_stats
99
+ end
100
+
101
+ # Returns a Hash of L4D2Weapon for this user containing all Left4Dead 2
102
+ # weapons.
103
+ # If the weapons haven't been parsed already, parsing is done now.
104
+ def weapon_stats
105
+ return unless public?
106
+
107
+ if @weapon_stats.nil?
108
+ @weapon_stats = {}
109
+ @xml_data.elements.each('stats/weapons/*') do |weapon_data|
110
+ next unless weapon_data.has_elements?
111
+
112
+ unless %w{bilejars molotov pipes}.include? weapon_data.name
113
+ weapon = L4D2Weapon.new(weapon_data)
114
+ else
115
+ weapon = L4DExplosive.new(weapon_data)
116
+ end
117
+
118
+ @weapon_stats[weapon_data.name] = weapon
119
+ end
120
+ end
121
+
122
+ @weapon_stats
123
+ end
124
+
125
+ end
@@ -0,0 +1,21 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2009, Sebastian Staudt
5
+
6
+ require 'steam/community/l4d/abstract_l4d_weapon'
7
+
8
+ class L4D2Weapon < AbstractL4DWeapon
9
+
10
+ attr_reader :damage, :weapon_group
11
+
12
+ # Creates a new instance of L4D2Weapon based on the assigned XML data
13
+ def initialize(weapon_data)
14
+ super weapon_data
15
+
16
+ @damage = weapon_data.elements['damage'].text.to_i
17
+ @kill_percentage = weapon_data.elements['pctkills'].text
18
+ @weapon_group = weapon_data.attribute('group')
19
+ end
20
+
21
+ end
@@ -3,6 +3,8 @@
3
3
  #
4
4
  # Copyright (c) 2009, Sebastian Staudt
5
5
 
6
+ # L4DMap holds statistical information about maps played by a player in
7
+ # Survival mode of Left4Dead.
6
8
  class L4DMap
7
9
 
8
10
  attr_reader :best_time, :id, :medal, :name, :times_played