steam-condenser 0.14.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +22 -0
  3. data/LICENSE +1 -1
  4. data/README.md +14 -6
  5. data/Rakefile +35 -0
  6. data/lib/{stringio_additions.rb → core_ext/stringio.rb} +1 -1
  7. data/lib/{exceptions/packet_format_exception.rb → errors/packet_format_error.rb} +5 -5
  8. data/lib/{exceptions/rcon_ban_exception.rb → errors/rcon_ban_error.rb} +5 -5
  9. data/lib/{exceptions/rcon_no_auth_exception.rb → errors/rcon_no_auth_error.rb} +5 -5
  10. data/lib/{exceptions/steam_condenser_exception.rb → errors/steam_condenser_error.rb} +3 -3
  11. data/lib/errors/timeout_error.rb +28 -0
  12. data/lib/{exceptions/web_api_exception.rb → errors/web_api_error.rb} +8 -8
  13. data/lib/steam/community/alien_swarm/alien_swarm_mission.rb +86 -11
  14. data/lib/steam/community/alien_swarm/alien_swarm_stats.rb +38 -15
  15. data/lib/steam/community/alien_swarm/alien_swarm_weapon.rb +29 -8
  16. data/lib/steam/community/app_news.rb +91 -27
  17. data/lib/steam/community/cacheable.rb +65 -21
  18. data/lib/steam/community/css/css_map.rb +39 -9
  19. data/lib/steam/community/css/css_stats.rb +32 -12
  20. data/lib/steam/community/css/css_weapon.rb +46 -10
  21. data/lib/steam/community/defense_grid/defense_grid_stats.rb +129 -17
  22. data/lib/steam/community/dods/dods_class.rb +66 -10
  23. data/lib/steam/community/dods/dods_stats.rb +20 -7
  24. data/lib/steam/community/dods/dods_weapon.rb +35 -24
  25. data/lib/steam/community/game_achievement.rb +50 -19
  26. data/lib/steam/community/game_class.rb +16 -5
  27. data/lib/steam/community/game_inventory.rb +37 -4
  28. data/lib/steam/community/game_item.rb +64 -3
  29. data/lib/steam/community/game_stats.rb +81 -16
  30. data/lib/steam/community/game_weapon.rb +29 -11
  31. data/lib/steam/community/l4d/abstract_l4d_stats.rb +91 -65
  32. data/lib/steam/community/l4d/abstract_l4d_weapon.rb +38 -8
  33. data/lib/steam/community/l4d/l4d2_map.rb +30 -5
  34. data/lib/steam/community/l4d/l4d2_stats.rb +83 -45
  35. data/lib/steam/community/l4d/l4d2_weapon.rb +20 -6
  36. data/lib/steam/community/l4d/l4d_explosive.rb +13 -5
  37. data/lib/steam/community/l4d/l4d_map.rb +35 -7
  38. data/lib/steam/community/l4d/l4d_stats.rb +23 -10
  39. data/lib/steam/community/l4d/l4d_weapon.rb +11 -7
  40. data/lib/steam/community/portal2/portal2_inventory.rb +4 -0
  41. data/lib/steam/community/portal2/portal2_item.rb +13 -1
  42. data/lib/steam/community/portal2/portal2_stats.rb +10 -6
  43. data/lib/steam/community/steam_game.rb +74 -0
  44. data/lib/steam/community/steam_group.rb +48 -14
  45. data/lib/steam/community/steam_id.rb +295 -64
  46. data/lib/steam/community/tf2/tf2_class.rb +66 -7
  47. data/lib/steam/community/tf2/tf2_class_factory.rb +14 -7
  48. data/lib/steam/community/tf2/tf2_engineer.rb +26 -6
  49. data/lib/steam/community/tf2/tf2_golden_wrench.rb +37 -10
  50. data/lib/steam/community/tf2/tf2_inventory.rb +4 -0
  51. data/lib/steam/community/tf2/tf2_item.rb +13 -1
  52. data/lib/steam/community/tf2/tf2_medic.rb +20 -5
  53. data/lib/steam/community/tf2/tf2_sniper.rb +15 -5
  54. data/lib/steam/community/tf2/tf2_spy.rb +20 -6
  55. data/lib/steam/community/tf2/tf2_stats.rb +20 -6
  56. data/lib/steam/community/web_api.rb +50 -32
  57. data/lib/steam/packets/c2m_checkmd5_packet.rb +1 -1
  58. data/lib/steam/packets/m2a_server_batch_packet.rb +3 -2
  59. data/lib/steam/packets/m2s_requestrestart_packet.rb +3 -3
  60. data/lib/steam/packets/rcon/rcon_packet_factory.rb +4 -4
  61. data/lib/steam/packets/request_with_challenge.rb +1 -1
  62. data/lib/steam/packets/s2a_info_base_packet.rb +1 -1
  63. data/lib/steam/packets/s2a_info_detailed_packet.rb +10 -10
  64. data/lib/steam/packets/s2a_player_packet.rb +5 -1
  65. data/lib/steam/packets/s2a_rules_packet.rb +4 -3
  66. data/lib/steam/packets/s2m_heartbeat2_packet.rb +2 -2
  67. data/lib/steam/packets/steam_packet.rb +1 -1
  68. data/lib/steam/packets/steam_packet_factory.rb +12 -16
  69. data/lib/steam/servers/game_server.rb +38 -32
  70. data/lib/steam/servers/goldsrc_server.rb +10 -1
  71. data/lib/steam/servers/master_server.rb +42 -21
  72. data/lib/steam/servers/server.rb +4 -5
  73. data/lib/steam/servers/source_server.rb +20 -5
  74. data/lib/steam/sockets/goldsrc_socket.rb +53 -22
  75. data/lib/steam/sockets/master_server_socket.rb +14 -4
  76. data/lib/steam/sockets/rcon_socket.rb +39 -6
  77. data/lib/steam/sockets/source_socket.rb +19 -15
  78. data/lib/steam/sockets/steam_socket.rb +33 -23
  79. data/lib/steam/steam_player.rb +86 -11
  80. data/lib/steam-condenser/community.rb +24 -24
  81. data/lib/steam-condenser/servers.rb +2 -2
  82. data/lib/steam-condenser/version.rb +3 -3
  83. data/steam-condenser.gemspec +23 -0
  84. data/test/query_tests.rb +12 -12
  85. data/test/rcon_tests.rb +3 -3
  86. data/test/steam/communtiy/steam_community_test_suite.rb +12 -0
  87. data/test/steam/communtiy/steam_group_tests.rb +6 -5
  88. data/test/steam/communtiy/steam_id_tests.rb +6 -5
  89. data/test/steam_community_tests.rb +3 -3
  90. data/test/stringio_additions_tests.rb +7 -7
  91. metadata +61 -43
  92. data/lib/exceptions/timeout_exception.rb +0 -24
  93. data/test/datagram_channel_tests.rb +0 -42
  94. data/test/socket_channel_tests.rb +0 -43
@@ -1,23 +1,41 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2009-2010, Sebastian Staudt
4
+ # Copyright (c) 2009-2011, Sebastian Staudt
5
5
 
6
- # Super class for classes representing game weapons
6
+ # A module implementing basic functionality for classes representing game
7
+ # weapons
8
+ #
9
+ # @author Sebastian Staudt
7
10
  module GameWeapon
8
11
 
9
- attr_reader :kills, :id, :shots
12
+ # Returns the number of kills achieved with this weapon
13
+ #
14
+ # @return [Fixnum] The number of kills achieved
15
+ attr_reader :kills
16
+
17
+ # Returns the unique identifier for this weapon
18
+ #
19
+ # @return [String] The identifier of this weapon
20
+ attr_reader :id
10
21
 
22
+ # Returns the number of shots fired with this weapon
23
+ #
24
+ # @return [Fixnum] The number of shots fired
25
+ attr_reader :shots
26
+
27
+ # Creates a new game weapon instance with the data provided
28
+ #
29
+ # @param [REXML::Element] weapon_data The data representing this weapon
11
30
  def initialize(weapon_data)
12
- @kills = weapon_data.elements['kills'].text.to_i
31
+ @kills = weapon_data.elements['kills'].text.to_i
13
32
  end
14
33
 
15
- # Returns the average number of shots needed for a kill with this weapon.
16
- # Calculates the value if needed.
34
+ # Returns the average number of shots needed for a kill with this weapon
35
+ #
36
+ # @return [Float] The average number of shots needed for a kill
17
37
  def avg_shots_per_kill
18
- @avg_shots_per_kill = @shots.to_f / @kills if @avg_shots_per_kill.nil?
19
-
20
- @avg_shots_per_kill
38
+ @shots.to_f / @kills
21
39
  end
22
40
 
23
41
  end
@@ -1,137 +1,163 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2009-2010, Sebastian Staudt
4
+ # Copyright (c) 2009-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/community/game_stats'
7
7
 
8
- # AbstractL4DStats is an abstract base class for statistics for Left4Dead and
9
- # Left4Dead 2. As both games have more or less the same statistics available in
10
- # the Steam Community the code for both is pretty much the same.
8
+ # This module is a base for statistics for Left4Dead and Left4Dead 2. As both
9
+ # games have more or less the same statistics available in the Steam Community
10
+ # the code for both is pretty much the same.
11
+ #
12
+ # @author Sebastian Staudt
11
13
  module AbstractL4DStats
12
14
 
15
+ # The names of the special infected in Left4Dead
13
16
  SPECIAL_INFECTED = %w(boomer hunter smoker tank)
14
17
 
18
+ # Creates a new instance of statistics for both, Left4Dead and Left4Dead 2
19
+ # parsing basic common data
20
+ #
21
+ # @param [String] steam_id The custom URL or 64bit Steam ID of the user
22
+ # @param [String] game_name The name of the game
15
23
  def initialize(steam_id, game_name)
16
24
  super steam_id, game_name
17
25
 
18
26
  if public?
19
27
  @most_recent_game = {}
20
28
  if @xml_data.elements['stats/mostrecentgame'].has_elements?
21
- @most_recent_game['difficulty'] = @xml_data.elements['stats/mostrecentgame/difficulty'].text
22
- @most_recent_game['escaped'] = (@xml_data.elements['stats/mostrecentgame/bEscaped'].text == 1)
23
- @most_recent_game['movie'] = @xml_data.elements['stats/mostrecentgame/movie'].text
24
- @most_recent_game['time_played'] = @xml_data.elements['stats/mostrecentgame/time'].text
29
+ @most_recent_game[:difficulty] = @xml_data.elements['stats/mostrecentgame/difficulty'].text
30
+ @most_recent_game[:escaped] = (@xml_data.elements['stats/mostrecentgame/bEscaped'].text == 1)
31
+ @most_recent_game[:movie] = @xml_data.elements['stats/mostrecentgame/movie'].text
32
+ @most_recent_game[:time_played] = @xml_data.elements['stats/mostrecentgame/time'].text
25
33
  end
26
34
  end
27
35
  end
28
36
 
29
- # Returns a Hash of favorites for this user like weapons and character.
37
+ # Returns a hash of favorites for this user like weapons and character
38
+ #
30
39
  # If the favorites haven't been parsed already, parsing is done now.
40
+ #
41
+ # @return [Hash<String, Object>] The favorites of this user
31
42
  def favorites
32
43
  return unless public?
33
44
 
34
45
  if @favorites.nil?
35
46
  @favorites = {}
36
- @favorites['campaign'] = @xml_data.elements['stats/favorites/campaign'].text
37
- @favorites['campaign_percentage'] = @xml_data.elements['stats/favorites/campaignpct'].text.to_i
38
- @favorites['character'] = @xml_data.elements['stats/favorites/character'].text
39
- @favorites['character_percentage'] = @xml_data.elements['stats/favorites/characterpct'].text.to_i
40
- @favorites['level1_weapon'] = @xml_data.elements['stats/favorites/weapon1'].text
41
- @favorites['level1_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon1pct'].text.to_i
42
- @favorites['level2_weapon'] = @xml_data.elements['stats/favorites/weapon2'].text
43
- @favorites['level2_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon2pct'].text.to_i
47
+ @favorites[:campaign] = @xml_data.elements['stats/favorites/campaign'].text
48
+ @favorites[:campaign_percentage] = @xml_data.elements['stats/favorites/campaignpct'].text.to_i
49
+ @favorites[:character] = @xml_data.elements['stats/favorites/character'].text
50
+ @favorites[:character_percentage] = @xml_data.elements['stats/favorites/characterpct'].text.to_i
51
+ @favorites[:level1_weapon] = @xml_data.elements['stats/favorites/weapon1'].text
52
+ @favorites[:level1_weapon_percentage] = @xml_data.elements['stats/favorites/weapon1pct'].text.to_i
53
+ @favorites[:level2_weapon] = @xml_data.elements['stats/favorites/weapon2'].text
54
+ @favorites[:level2_weapon_percentage] = @xml_data.elements['stats/favorites/weapon2pct'].text.to_i
44
55
  end
45
56
 
46
57
  @favorites
47
58
  end
48
59
 
49
- # Returns a Hash of lifetime statistics for this user like the time played.
50
- # If the lifetime statistics haven't been parsed already, parsing is done now.
60
+ # Returns a hash of lifetime statistics for this user like the time played
61
+ #
62
+ # If the lifetime statistics haven't been parsed already, parsing is done
63
+ # now.
64
+ #
65
+ # @return [Hash<String, Object>] The lifetime statistics for this user
51
66
  def lifetime_stats
52
67
  return unless public?
53
68
 
54
69
  if @lifetime_stats.nil?
55
70
  @lifetime_stats = {}
56
- @lifetime_stats['finales_survived'] = @xml_data.elements['stats/lifetime/finales'].text.to_i
57
- @lifetime_stats['games_played'] = @xml_data.elements['stats/lifetime/gamesplayed'].text.to_i
58
- @lifetime_stats['infected_killed'] = @xml_data.elements['stats/lifetime/infectedkilled'].text.to_i
59
- @lifetime_stats['kills_per_hour'] = @xml_data.elements['stats/lifetime/killsperhour'].text.to_f
60
- @lifetime_stats['avg_kits_shared'] = @xml_data.elements['stats/lifetime/kitsshared'].text.to_f
61
- @lifetime_stats['avg_kits_used'] = @xml_data.elements['stats/lifetime/kitsused'].text.to_f
62
- @lifetime_stats['avg_pills_shared'] = @xml_data.elements['stats/lifetime/pillsshared'].text.to_f
63
- @lifetime_stats['avg_pills_used'] = @xml_data.elements['stats/lifetime/pillsused'].text.to_f
64
- @lifetime_stats['time_played'] = @xml_data.elements['stats/lifetime/timeplayed'].text
65
-
66
- @lifetime_stats['finales_survived_percentage'] = @lifetime_stats['finales_survived'].to_f / @lifetime_stats['games_played']
71
+ @lifetime_stats[:finales_survived] = @xml_data.elements['stats/lifetime/finales'].text.to_i
72
+ @lifetime_stats[:games_played] = @xml_data.elements['stats/lifetime/gamesplayed'].text.to_i
73
+ @lifetime_stats[:infected_killed] = @xml_data.elements['stats/lifetime/infectedkilled'].text.to_i
74
+ @lifetime_stats[:kills_per_hour] = @xml_data.elements['stats/lifetime/killsperhour'].text.to_f
75
+ @lifetime_stats[:avg_kits_shared] = @xml_data.elements['stats/lifetime/kitsshared'].text.to_f
76
+ @lifetime_stats[:avg_kits_used] = @xml_data.elements['stats/lifetime/kitsused'].text.to_f
77
+ @lifetime_stats[:avg_pills_shared] = @xml_data.elements['stats/lifetime/pillsshared'].text.to_f
78
+ @lifetime_stats[:avg_pills_used] = @xml_data.elements['stats/lifetime/pillsused'].text.to_f
79
+ @lifetime_stats[:time_played] = @xml_data.elements['stats/lifetime/timeplayed'].text
80
+
81
+ @lifetime_stats[:finales_survived_percentage] = @lifetime_stats[:finales_survived].to_f / @lifetime_stats[:games_played]
67
82
  end
68
83
 
69
84
  @lifetime_stats
70
85
  end
71
86
 
72
- # Returns a Hash of Survival statistics for this user like revived teammates.
73
- # If the Survival statistics haven't been parsed already, parsing is done now.
87
+ # Returns a hash of Survival statistics for this user like revived teammates
88
+ #
89
+ # If the Survival statistics haven't been parsed already, parsing is done
90
+ # now.
91
+ #
92
+ # @return [Hash<String, Object>] The Survival statistics for this user
74
93
  def survival_stats
75
94
  return unless public?
76
95
 
77
96
  if @survival_stats.nil?
78
97
  @survival_stats = {}
79
- @survival_stats['gold_medals'] = @xml_data.elements['stats/survival/goldmedals'].text.to_i
80
- @survival_stats['silver_medals'] = @xml_data.elements['stats/survival/silvermedals'].text.to_i
81
- @survival_stats['bronze_medals'] = @xml_data.elements['stats/survival/bronzemedals'].text.to_i
82
- @survival_stats['rounds_played'] = @xml_data.elements['stats/survival/roundsplayed'].text.to_i
83
- @survival_stats['best_time'] = @xml_data.elements['stats/survival/besttime'].text.to_f
98
+ @survival_stats[:gold_medals] = @xml_data.elements['stats/survival/goldmedals'].text.to_i
99
+ @survival_stats[:silver_medals] = @xml_data.elements['stats/survival/silvermedals'].text.to_i
100
+ @survival_stats[:bronze_medals] = @xml_data.elements['stats/survival/bronzemedals'].text.to_i
101
+ @survival_stats[:rounds_played] = @xml_data.elements['stats/survival/roundsplayed'].text.to_i
102
+ @survival_stats[:best_time] = @xml_data.elements['stats/survival/besttime'].text.to_f
84
103
  end
85
104
 
86
105
  @survival_stats
87
106
  end
88
107
 
89
- # Returns a Hash of teamplay statistics for this user like revived teammates.
90
- # If the teamplay statistics haven't been parsed already, parsing is done now.
108
+ # Returns a hash of teamplay statistics for this user like revived teammates
109
+ #
110
+ # If the teamplay statistics haven't been parsed already, parsing is done
111
+ # now.
112
+ #
113
+ # @return [Hash<String, Object>] The teamplay statistics for this
91
114
  def teamplay_stats
92
115
  return unless public?
93
116
 
94
117
  if @teamplay_stats.nil?
95
118
  @teamplay_stats = {}
96
- @teamplay_stats['revived'] = @xml_data.elements['stats/teamplay/revived'].text.to_i
97
- @teamplay_stats['most_revived_difficulty'] = @xml_data.elements['stats/teamplay/reviveddiff'].text
98
- @teamplay_stats['avg_revived'] = @xml_data.elements['stats/teamplay/revivedavg'].text.to_f
99
- @teamplay_stats['avg_was_revived'] = @xml_data.elements['stats/teamplay/wasrevivedavg'].text.to_f
100
- @teamplay_stats['protected'] = @xml_data.elements['stats/teamplay/protected'].text.to_i
101
- @teamplay_stats['most_protected_difficulty'] = @xml_data.elements['stats/teamplay/protecteddiff'].text
102
- @teamplay_stats['avg_protected'] = @xml_data.elements['stats/teamplay/protectedavg'].text.to_f
103
- @teamplay_stats['avg_was_protected'] = @xml_data.elements['stats/teamplay/wasprotectedavg'].text.to_f
104
- @teamplay_stats['friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamage'].text.to_i
105
- @teamplay_stats['most_friendly_fire_difficulty'] = @xml_data.elements['stats/teamplay/ffdamagediff'].text
106
- @teamplay_stats['avg_friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamageavg'].text.to_f
119
+ @teamplay_stats[:revived] = @xml_data.elements['stats/teamplay/revived'].text.to_i
120
+ @teamplay_stats[:most_revived_difficulty] = @xml_data.elements['stats/teamplay/reviveddiff'].text
121
+ @teamplay_stats[:avg_revived] = @xml_data.elements['stats/teamplay/revivedavg'].text.to_f
122
+ @teamplay_stats[:avg_was_revived] = @xml_data.elements['stats/teamplay/wasrevivedavg'].text.to_f
123
+ @teamplay_stats[:protected] = @xml_data.elements['stats/teamplay/protected'].text.to_i
124
+ @teamplay_stats[:most_protected_difficulty] = @xml_data.elements['stats/teamplay/protecteddiff'].text
125
+ @teamplay_stats[:avg_protected] = @xml_data.elements['stats/teamplay/protectedavg'].text.to_f
126
+ @teamplay_stats[:avg_was_protected] = @xml_data.elements['stats/teamplay/wasprotectedavg'].text.to_f
127
+ @teamplay_stats[:friendly_fire_damage] = @xml_data.elements['stats/teamplay/ffdamage'].text.to_i
128
+ @teamplay_stats[:most_friendly_fire_difficulty] = @xml_data.elements['stats/teamplay/ffdamagediff'].text
129
+ @teamplay_stats[:avg_friendly_fire_damage] = @xml_data.elements['stats/teamplay/ffdamageavg'].text.to_f
107
130
  end
108
131
 
109
132
  @teamplay_stats
110
133
  end
111
134
 
112
- # Returns a Hash of Versus statistics for this user like percentage of rounds
113
- # won.
135
+ # Returns a hash of Versus statistics for this user like percentage of rounds
136
+ # won
137
+ #
114
138
  # If the Versus statistics haven't been parsed already, parsing is done now.
139
+ #
140
+ # @return [Hash<String, Object>] The Versus statistics for this user
115
141
  def versus_stats
116
142
  return unless public?
117
143
 
118
144
  if @versus_stats.nil?
119
145
  @versus_stats = {}
120
- @versus_stats['games_played'] = @xml_data.elements['stats/versus/gamesplayed'].text.to_i
121
- @versus_stats['games_completed'] = @xml_data.elements['stats/versus/gamescompleted'].text.to_i
122
- @versus_stats['finales_survived'] = @xml_data.elements['stats/versus/finales'].text.to_i
123
- @versus_stats['points'] = @xml_data.elements['stats/versus/points'].text.to_i
124
- @versus_stats['most_points_infected'] = @xml_data.elements['stats/versus/pointsas'].text
125
- @versus_stats['games_won'] = @xml_data.elements['stats/versus/gameswon'].text.to_i
126
- @versus_stats['games_lost'] = @xml_data.elements['stats/versus/gameslost'].text.to_i
127
- @versus_stats['highest_survivor_score'] = @xml_data.elements['stats/versus/survivorscore'].text.to_i
146
+ @versus_stats[:games_played] = @xml_data.elements['stats/versus/gamesplayed'].text.to_i
147
+ @versus_stats[:games_completed] = @xml_data.elements['stats/versus/gamescompleted'].text.to_i
148
+ @versus_stats[:finales_survived] = @xml_data.elements['stats/versus/finales'].text.to_i
149
+ @versus_stats[:points] = @xml_data.elements['stats/versus/points'].text.to_i
150
+ @versus_stats[:most_points_infected] = @xml_data.elements['stats/versus/pointsas'].text
151
+ @versus_stats[:games_won] = @xml_data.elements['stats/versus/gameswon'].text.to_i
152
+ @versus_stats[:games_lost] = @xml_data.elements['stats/versus/gameslost'].text.to_i
153
+ @versus_stats[:highest_survivor_score] = @xml_data.elements['stats/versus/survivorscore'].text.to_i
128
154
 
129
- @versus_stats['finales_survived_percentage'] = @versus_stats['finales_survived'].to_f / @versus_stats['games_played']
155
+ @versus_stats[:finales_survived_percentage] = @versus_stats[:finales_survived].to_f / @versus_stats[:games_played]
130
156
 
131
157
  self.class.const_get(:SPECIAL_INFECTED).each do |infected|
132
158
  @versus_stats[infected] = {}
133
- @versus_stats[infected]['special_attacks'] = @xml_data.elements["stats/versus/#{infected}special"].text.to_i
134
- @versus_stats[infected]['most_damage'] = @xml_data.elements["stats/versus/#{infected}dmg"].text.to_i
159
+ @versus_stats[infected][:special_attacks] = @xml_data.elements["stats/versus/#{infected}special"].text.to_i
160
+ @versus_stats[infected][:most_damage] = @xml_data.elements["stats/versus/#{infected}dmg"].text.to_i
135
161
  @versus_stats[infected]['avg_lifespan'] = @xml_data.elements["stats/versus/#{infected}lifespan"].text.to_i
136
162
  end
137
163
  end
@@ -1,23 +1,53 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2009-2010, Sebastian Staudt
4
+ # Copyright (c) 2009-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/community/game_weapon'
7
7
 
8
+ # This abstract class is a base class for weapons in Left4Dead and Left4Dead 2
9
+ # as the weapon stats for both games are very similar
10
+ #
11
+ # @author Sebastian Staudt
8
12
  module AbstractL4DWeapon
9
13
 
10
14
  include GameWeapon
11
15
 
12
- attr_reader :accuracy, :headshots_percentage, :kill_percentage
16
+ # Returns the overall accuracy of the player with this weapon
17
+ #
18
+ # @return [String] The accuracy of the player with this weapon
19
+ attr_reader :accuracy
20
+
21
+ # Returns the percentage of kills with this weapon that have been headshots
22
+ #
23
+ # @return [String] The percentage of headshots with this weapon
24
+ attr_reader :headshots_percentage
25
+
26
+ # Returns the ID of the weapon
27
+ #
28
+ # @return [String] The ID of the weapon
29
+ attr_reader :id
30
+
31
+ # Returns the percentage of overall kills of the player that have been
32
+ # achieved with this weapon
33
+ #
34
+ # @return [String] The percentage of kills with this weapon
35
+ attr_reader :kill_percentage
36
+
37
+ # Returns the number of shots the player has fired with this weapon
38
+ #
39
+ # @return [Fixnum] The number of shots with this weapon
40
+ attr_reader :shots
13
41
 
14
- # Abstract base constructor which parses common data for both, L4DWeapon and
15
- # L4D2Weapon
42
+ # Creates a new instance of weapon from the given XML data and parses common
43
+ # data for both, `L4DWeapon` and `L4D2Weapon`
44
+ #
45
+ # @param [REXML::Element] weapon_data The XML data for this weapon
16
46
  def initialize(weapon_data)
17
47
  super weapon_data
18
48
 
19
- @accuracy = weapon_data.elements['accuracy'].text
20
- @headshots_percentage = weapon_data.elements['headshots'].text
49
+ @accuracy = weapon_data.elements['accuracy'].text.to_f * 0.01
50
+ @headshots_percentage = weapon_data.elements['headshots'].text.to_f * 0.01
21
51
  @id = weapon_data.name
22
52
  @shots = weapon_data.elements['shots'].text.to_i
23
53
  end
@@ -1,7 +1,7 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2009-2010, Sebastian Staudt
4
+ # Copyright (c) 2009-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/community/steam_id'
7
7
  require 'steam/community/l4d/l4d_map'
@@ -10,18 +10,40 @@ require 'steam/community/l4d/l4d_map'
10
10
  # Survival mode of Left4Dead 2. The basic information provided is more or less
11
11
  # the same for Left4Dead and Left4Dead 2, but parsing has to be done
12
12
  # differently.
13
+ #
14
+ # @author Sebastian Staudt
13
15
  class L4D2Map < L4DMap
14
16
 
15
- attr_reader :items, :kills, :teammates
17
+ # Returns statistics about the items used by the player on this map
18
+ #
19
+ # @return [Hash<Symbol, Fixnum>] The items used by the player
20
+ attr_reader :items
16
21
 
22
+ # Returns the number of special infected killed by the player grouped by
23
+ # the names of the special infected
24
+ #
25
+ # @return [Hash<Symbol, Fixnum>] The special infected killed by the player
26
+ attr_reader :kills
27
+
28
+ # Returns the SteamIDs of the teammates of the player in his best game on
29
+ # this map
30
+ #
31
+ # @return [Array<SteamId>] The SteamIDs of the teammates in the best game
32
+ attr_reader :teammates
33
+
34
+ # The names of the special infected in Left4Dead 2
17
35
  INFECTED = %w{boomer charger common hunter jockey smoker spitter tank}
36
+
37
+ # The items available in Left4Dead 2
18
38
  ITEMS = %w{adrenaline defibs medkits pills}
19
39
 
20
- # Creates a new instance of L4D2Map based on the assigned XML data
40
+ # Creates a new instance of a map based on the given XML data
21
41
  #
22
42
  # The map statistics for the Survival mode of Left4Dead 2 hold much more
23
43
  # information than those for Left4Dead, e.g. the teammates and items are
24
44
  # listed.
45
+ #
46
+ # @param [REXML::Element] map_data The XML data for this map
25
47
  def initialize(map_data)
26
48
  @id = map_data.elements['img'].text.match(/http:\/\/steamcommunity\.com\/public\/images\/gamestats\/550\/(.*).jpg/)[1]
27
49
  @name = map_data.elements['name'].text
@@ -58,6 +80,9 @@ class L4D2Map < L4DMap
58
80
  end
59
81
  end
60
82
 
83
+ # Returns whether the player has already played this map
84
+ #
85
+ # @return [Boolean] `true` if the player has already played this map
61
86
  def played?
62
87
  @played
63
88
  end
@@ -1,108 +1,146 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2009-2010, Sebastian Staudt
4
+ # Copyright (c) 2009-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/community/l4d/abstract_l4d_stats'
7
7
  require 'steam/community/l4d/l4d2_map'
8
8
  require 'steam/community/l4d/l4d2_weapon'
9
9
 
10
+ # This class represents the game statistics for a single user in Left4Dead 2
11
+ #
12
+ # @author Sebastian Staudt
10
13
  class L4D2Stats < GameStats
11
14
 
12
15
  include AbstractL4DStats
13
16
 
17
+ # The names of the special infected in Left4Dead 2
14
18
  SPECIAL_INFECTED = SPECIAL_INFECTED + %w{charger jockey spitter}
15
19
 
16
- # Creates a L4D2Stats object by calling the super constructor with the game
17
- # name "l4d2"
20
+ # Returns the percentage of damage done by this player with each weapon type
21
+ #
22
+ # Available weapon types are `:melee`, `:pistols`, `:rifles` and `:shotguns`.
23
+ #
24
+ # @return [Hash<Symbol, Float>] The percentages of damage done with each
25
+ # weapon type
26
+ attr_reader :damage_percentages
27
+
28
+ # Creates a `L4D2Stats` object by calling the super constructor with the game
29
+ # name `'l4d2'`
30
+ #
31
+ # @param [String] steam_id The custom URL or 64bit Steam ID of the user
18
32
  def initialize(steam_id)
19
33
  super steam_id, 'l4d2'
34
+
35
+ @damage_percentages = {
36
+ :melee => @xml_data.elements['stats/weapons/meleepctdmg'].text.to_f,
37
+ :pistols => @xml_data.elements['stats/weapons/pistolspctdmg'].text.to_f,
38
+ :rifles => @xml_data.elements['stats/weapons/bulletspctdmg'].text.to_f,
39
+ :shotguns => @xml_data.elements['stats/weapons/shellspctdmg'].text.to_f
40
+ }
20
41
  end
21
42
 
22
- # Returns a Hash of lifetime statistics for this user like the time played.
23
- # If the lifetime statistics haven't been parsed already, parsing is done now.
43
+ # Returns a hash of lifetime statistics for this user like the time played
44
+ #
45
+ # If the lifetime statistics haven't been parsed already, parsing is done
46
+ # now.
24
47
  #
25
- # There are only a few additional lifetime statistics for Left4Dead 2 which
26
- # are not generated for Left4Dead, so this calls
27
- # AbstractL4DStats#lifetime_stats first and adds some additional stats.
48
+ # There are only a few additional lifetime statistics for Left4Dead 2
49
+ # which are not generated for Left4Dead, so this calls
50
+ # {AbstractL4DStats#lifetime_stats} first and adds some additional stats.
51
+ #
52
+ # @return [Hash<String, Object>] The lifetime statistics of the player in
53
+ # Left4Dead 2
28
54
  def lifetime_stats
29
55
  return unless public?
30
56
 
31
57
  if @lifetime_stats.nil?
32
58
  super
33
- @lifetime_stats['avg_adrenaline_shared'] = @xml_data.elements['stats/lifetime/adrenalineshared'].text.to_f
34
- @lifetime_stats['avg_adrenaline_used'] = @xml_data.elements['stats/lifetime/adrenalineused'].text.to_f
35
- @lifetime_stats['avg_defibrillators_used'] = @xml_data.elements['stats/lifetime/defibrillatorsused'].text.to_f
59
+ @lifetime_stats[:avg_adrenaline_shared] = @xml_data.elements['stats/lifetime/adrenalineshared'].text.to_f
60
+ @lifetime_stats[:avg_adrenaline_used] = @xml_data.elements['stats/lifetime/adrenalineused'].text.to_f
61
+ @lifetime_stats[:avg_defibrillators_used] = @xml_data.elements['stats/lifetime/defibrillatorsused'].text.to_f
36
62
  end
37
63
 
38
64
  @lifetime_stats
39
65
  end
40
66
 
41
- # Returns a Hash of Scavenge statistics for this user like the number of
42
- # Scavenge rounds played.
43
- # If the Scavenge statistics haven't been parsed already, parsing is done now.
67
+ # Returns a hash of Scavenge statistics for this user like the number of
68
+ # Scavenge rounds played
69
+ #
70
+ # If the Scavenge statistics haven't been parsed already, parsing is done
71
+ # now.
72
+ #
73
+ # @return [Hash<String, Object>] The Scavenge statistics of the player
44
74
  def scavenge_stats
45
75
  return unless public?
46
76
 
47
77
  if @scavenge_stats.nil?
48
78
  @scavenge_stats = {}
49
- @scavenge_stats['avg_cans_per_round'] = @xml_data.elements['stats/scavenge/avgcansperround'].text.to_f
50
- @scavenge_stats['perfect_rounds'] = @xml_data.elements['stats/scavenge/perfect16canrounds'].text.to_i
51
- @scavenge_stats['rounds_lost'] = @xml_data.elements['stats/scavenge/roundslost'].text.to_i
52
- @scavenge_stats['rounds_played'] = @xml_data.elements['stats/scavenge/roundsplayed'].text.to_i
53
- @scavenge_stats['rounds_won'] = @xml_data.elements['stats/scavenge/roundswon'].text.to_i
54
- @scavenge_stats['total_cans'] = @xml_data.elements['stats/scavenge/totalcans'].text.to_i
55
-
56
- @scavenge_stats['maps'] = {}
79
+ @scavenge_stats[:avg_cans_per_round] = @xml_data.elements['stats/scavenge/avgcansperround'].text.to_f
80
+ @scavenge_stats[:perfect_rounds] = @xml_data.elements['stats/scavenge/perfect16canrounds'].text.to_i
81
+ @scavenge_stats[:rounds_lost] = @xml_data.elements['stats/scavenge/roundslost'].text.to_i
82
+ @scavenge_stats[:rounds_played] = @xml_data.elements['stats/scavenge/roundsplayed'].text.to_i
83
+ @scavenge_stats[:rounds_won] = @xml_data.elements['stats/scavenge/roundswon'].text.to_i
84
+ @scavenge_stats[:total_cans] = @xml_data.elements['stats/scavenge/totalcans'].text.to_i
85
+
86
+ @scavenge_stats[:maps] = {}
57
87
  @xml_data.elements.each('stats/scavenge/mapstats/map') do |map_data|
58
88
  map_id = map_data.elements['name'].text
59
- @scavenge_stats['maps'][map_id] = {}
60
- @scavenge_stats['maps'][map_id]['avg_round_score'] = map_data.elements['avgscoreperround'].text.to_i
61
- @scavenge_stats['maps'][map_id]['highest_game_score'] = map_data.elements['highgamescore'].text.to_i
62
- @scavenge_stats['maps'][map_id]['highest_round_score'] = map_data.elements['highroundscore'].text.to_i
63
- @scavenge_stats['maps'][map_id]['name'] = map_data.elements['fullname'].text
64
- @scavenge_stats['maps'][map_id]['rounds_played'] = map_data.elements['roundsplayed'].text.to_i
65
- @scavenge_stats['maps'][map_id]['rounds_won'] = map_data.elements['roundswon'].text.to_i
89
+ @scavenge_stats[:maps][map_id] = {}
90
+ @scavenge_stats[:maps][map_id]['avg_round_score'] = map_data.elements['avgscoreperround'].text.to_i
91
+ @scavenge_stats[:maps][map_id]['highest_game_score'] = map_data.elements['highgamescore'].text.to_i
92
+ @scavenge_stats[:maps][map_id]['highest_round_score'] = map_data.elements['highroundscore'].text.to_i
93
+ @scavenge_stats[:maps][map_id]['name'] = map_data.elements['fullname'].text
94
+ @scavenge_stats[:maps][map_id]['rounds_played'] = map_data.elements['roundsplayed'].text.to_i
95
+ @scavenge_stats[:maps][map_id]['rounds_won'] = map_data.elements['roundswon'].text.to_i
66
96
  end
67
97
 
68
- @scavenge_stats['infected'] = {}
98
+ @scavenge_stats[:infected] = {}
69
99
  @xml_data.elements.each('stats/scavenge/infectedstats/special') do |infected_data|
70
100
  infected_id = infected_data.elements['name'].text
71
- @scavenge_stats['infected'][infected_id] = {}
72
- @scavenge_stats['infected'][infected_id]['max_damage_per_life'] = infected_data.elements['maxdmg1life'].text.to_i
73
- @scavenge_stats['infected'][infected_id]['max_pours_interrupted'] = infected_data.elements['maxpoursinterrupted'].text.to_i
74
- @scavenge_stats['infected'][infected_id]['special_attacks'] = infected_data.elements['specialattacks'].text.to_i
101
+ @scavenge_stats[:infected][infected_id] = {}
102
+ @scavenge_stats[:infected][infected_id]['max_damage_per_life'] = infected_data.elements['maxdmg1life'].text.to_i
103
+ @scavenge_stats[:infected][infected_id]['max_pours_interrupted'] = infected_data.elements['maxpoursinterrupted'].text.to_i
104
+ @scavenge_stats[:infected][infected_id]['special_attacks'] = infected_data.elements['specialattacks'].text.to_i
75
105
  end
76
106
  end
77
107
 
78
108
  @scavenge_stats
79
109
  end
80
110
 
81
- # Returns a Hash of Survival statistics for this user like revived teammates.
82
- # If the Survival statistics haven't been parsed already, parsing is done now.
111
+ # Returns a hash of Survival statistics for this user like revived teammates
112
+ #
113
+ # If the Survival statistics haven't been parsed already, parsing is done
114
+ # now.
83
115
  #
84
116
  # The XML layout for the Survival statistics for Left4Dead 2 differs a bit
85
- # from Left4Dead's Survival statistics. So we have to use a different way of
86
- # parsing for the maps and we use a different map class (L4D2Map) which holds
87
- # the additional information provided in Left4Dead 2's statistics.
117
+ # from Left4Dead's Survival statistics. So we have to use a different way
118
+ # of parsing for the maps and we use a different map class
119
+ # (`L4D2Map`) which holds the additional information provided in
120
+ # Left4Dead 2's statistics.
121
+ #
122
+ # @return [Hash<String, Object>] The Survival statistics of the player
88
123
  def survival_stats
89
124
  return unless public?
90
125
 
91
126
  if @survival_stats.nil?
92
127
  super
93
- @survival_stats['maps'] = {}
128
+ @survival_stats[:maps] = {}
94
129
  @xml_data.elements.each('stats/survival/maps/map') do |map_data|
95
130
  map = L4D2Map.new(map_data)
96
- @survival_stats['maps'][map.id] = map
131
+ @survival_stats[:maps][map.id] = map
97
132
  end
98
133
  end
99
134
 
100
135
  @survival_stats
101
136
  end
102
137
 
103
- # Returns a Hash of L4D2Weapon for this user containing all Left4Dead 2
104
- # weapons.
138
+ # Returns a hash of `L4D2Weapon` for this user containing all Left4Dead 2
139
+ # weapons
140
+ #
105
141
  # If the weapons haven't been parsed already, parsing is done now.
142
+ #
143
+ # @return [Hash<String, Object>] The weapon statistics for this player
106
144
  def weapon_stats
107
145
  return unless public?
108
146