bnet 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +16 -0
  4. data/.travis.yml +15 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +120 -0
  9. data/Rakefile +14 -0
  10. data/TODO.md +74 -0
  11. data/bnet.gemspec +34 -0
  12. data/fixtures/cassettes/diablo_hero_found.yml +1023 -0
  13. data/fixtures/cassettes/diablo_hero_notf_found.yml +48 -0
  14. data/fixtures/cassettes/diablo_hero_reload.yml +1023 -0
  15. data/fixtures/cassettes/find_diablo_career_doesnt_exist.yml +93 -0
  16. data/fixtures/cassettes/find_diablo_career_player_one_.yml +2803 -0
  17. data/fixtures/cassettes/sc2_profile_found.yml +523 -0
  18. data/fixtures/cassettes/sc2_profile_not_found.yml +49 -0
  19. data/fixtures/cassettes/wow_character_found.yml +46 -0
  20. data/fixtures/cassettes/wow_character_not_found.yml +42 -0
  21. data/fixtures/cassettes/wow_data_battlegroups_all.yml +45 -0
  22. data/fixtures/cassettes/wow_data_character_races_all.yml +45 -0
  23. data/lib/bnet.rb +34 -0
  24. data/lib/bnet/account.rb +4 -0
  25. data/lib/bnet/api.rb +21 -0
  26. data/lib/bnet/bnet_resource.rb +25 -0
  27. data/lib/bnet/client.rb +6 -0
  28. data/lib/bnet/configuration.rb +7 -0
  29. data/lib/bnet/diablo3.rb +11 -0
  30. data/lib/bnet/diablo3/career.rb +91 -0
  31. data/lib/bnet/diablo3/hero.rb +131 -0
  32. data/lib/bnet/diablo3/skill.rb +19 -0
  33. data/lib/bnet/starcraft2.rb +7 -0
  34. data/lib/bnet/starcraft2/profile.rb +94 -0
  35. data/lib/bnet/version.rb +3 -0
  36. data/lib/bnet/wow.rb +7 -0
  37. data/lib/bnet/wow/character.rb +78 -0
  38. data/lib/bnet/wow/data.rb +5 -0
  39. data/lib/bnet/wow/data/base.rb +54 -0
  40. data/lib/bnet/wow/data/battlegroup.rb +18 -0
  41. data/lib/bnet/wow/data/character_race.rb +15 -0
  42. data/spec/bnet/account_spec.rb +5 -0
  43. data/spec/bnet/api_spec.rb +20 -0
  44. data/spec/bnet/diablo3/career_spec.rb +57 -0
  45. data/spec/bnet/diablo3/hero_spec.rb +89 -0
  46. data/spec/bnet/diablo3/skill_spec.rb +26 -0
  47. data/spec/bnet/diablo3_spec.rb +19 -0
  48. data/spec/bnet/starcraft2/profile_spec.rb +53 -0
  49. data/spec/bnet/wow/character_spec.rb +57 -0
  50. data/spec/bnet/wow/data/base_spec.rb +9 -0
  51. data/spec/bnet/wow/data/battlegroup_spec.rb +17 -0
  52. data/spec/bnet/wow/data/character_race_spec.rb +19 -0
  53. data/spec/bnet/wow/data_spec.rb +21 -0
  54. data/spec/bnet_spec.rb +8 -0
  55. data/spec/secrets_and_all_that.rb.sample +8 -0
  56. data/spec/secrets_and_all_that.rb.travis +8 -0
  57. data/spec/spec_helper.rb +29 -0
  58. metadata +285 -0
@@ -0,0 +1,49 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://us.api.battle.net/sc2/profile/2143215/1/PlayeZero/?apikey=api_key_from_secrets_rb&locale=en_US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Content-Language:
22
+ - en-US
23
+ Content-Type:
24
+ - application/json;charset=UTF-8
25
+ Date:
26
+ - Fri, 29 Aug 2014 08:40:09 GMT
27
+ Server:
28
+ - Apache
29
+ Vary:
30
+ - Accept-Encoding
31
+ X-Frame-Options:
32
+ - SAMEORIGIN
33
+ X-Mashery-Responder:
34
+ - prod-j-worker-us-east-1b-45.mashery.com
35
+ Transfer-Encoding:
36
+ - chunked
37
+ Connection:
38
+ - keep-alive
39
+ body:
40
+ encoding: UTF-8
41
+ string: |-
42
+ {
43
+ "status" : "nok",
44
+ "code" : 404,
45
+ "message" : "Sc2 Profile Not Found"
46
+ }
47
+ http_version:
48
+ recorded_at: Fri, 29 Aug 2014 08:40:09 GMT
49
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,46 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://us.api.battle.net/wow/character/Dragonmaw/AlexeiStukov?apikey=api_key_from_secrets_rb&locale=en_US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Language:
22
+ - en-US
23
+ Content-Type:
24
+ - application/json;charset=UTF-8
25
+ Date:
26
+ - Sat, 30 Aug 2014 15:05:25 GMT
27
+ Last-Modified:
28
+ - Mon, 06 Jan 2014 22:41:29 GMT
29
+ Server:
30
+ - Apache
31
+ Vary:
32
+ - Accept-Encoding
33
+ X-Frame-Options:
34
+ - SAMEORIGIN
35
+ X-Mashery-Responder:
36
+ - prod-j-worker-us-east-1e-49.mashery.com
37
+ Content-Length:
38
+ - '209'
39
+ Connection:
40
+ - keep-alive
41
+ body:
42
+ encoding: UTF-8
43
+ string: '{"lastModified":1389048089000,"name":"Alexeistukov","realm":"Dragonmaw","battlegroup":"Reckoning","class":2,"race":10,"gender":0,"level":85,"achievementPoints":1980,"thumbnail":"dragonmaw/68/70154564-avatar.jpg","calcClass":"b","totalHonorableKills":563}'
44
+ http_version:
45
+ recorded_at: Sat, 30 Aug 2014 15:05:27 GMT
46
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,42 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://us.api.battle.net/wow/character/Dragonmaw/NotHereYo?apikey=api_key_from_secrets_rb&locale=en_US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Content-Type:
22
+ - application/json;charset=utf-8
23
+ Date:
24
+ - Sat, 30 Aug 2014 15:07:50 GMT
25
+ Server:
26
+ - Apache
27
+ Vary:
28
+ - Accept-Encoding
29
+ X-Frame-Options:
30
+ - SAMEORIGIN
31
+ X-Mashery-Responder:
32
+ - prod-j-worker-us-east-1e-40.mashery.com
33
+ Content-Length:
34
+ - '70'
35
+ Connection:
36
+ - keep-alive
37
+ body:
38
+ encoding: UTF-8
39
+ string: '{"status":"nok", "reason": "Character not found."}'
40
+ http_version:
41
+ recorded_at: Sat, 30 Aug 2014 15:07:52 GMT
42
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://us.api.battle.net/wow/data/battlegroups/?apikey=api_key_from_secrets_rb&locale=en_US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Language:
22
+ - en-US
23
+ Content-Type:
24
+ - application/json;charset=UTF-8
25
+ Date:
26
+ - Sun, 31 Aug 2014 14:41:08 GMT
27
+ Server:
28
+ - Apache
29
+ Vary:
30
+ - Accept-Encoding
31
+ X-Frame-Options:
32
+ - SAMEORIGIN
33
+ X-Mashery-Responder:
34
+ - prod-j-worker-us-east-1e-40.mashery.com
35
+ Content-Length:
36
+ - '222'
37
+ Connection:
38
+ - keep-alive
39
+ body:
40
+ encoding: UTF-8
41
+ string: '{"battlegroups":[{"name":"Bloodlust","slug":"bloodlust"},{"name":"Coliseum
42
+ 1","slug":"coliseum-1"},{"name":"Cyclone","slug":"cyclone"},{"name":"Emberstorm","slug":"emberstorm"},{"name":"Nightfall","slug":"nightfall"},{"name":"Rampage","slug":"rampage"},{"name":"Reckoning","slug":"reckoning"},{"name":"Retaliation","slug":"retaliation"},{"name":"Ruin","slug":"ruin"},{"name":"Shadowburn","slug":"shadowburn"},{"name":"Stormstrike","slug":"stormstrike"},{"name":"Vengeance","slug":"vengeance"},{"name":"Vindication","slug":"vindication"},{"name":"Whirlwind","slug":"whirlwind"}]}'
43
+ http_version:
44
+ recorded_at: Sun, 31 Aug 2014 14:41:12 GMT
45
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://us.api.battle.net/wow/data/character/races?apikey=api_key_from_secrets_rb&locale=en_US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Language:
22
+ - en-US
23
+ Content-Type:
24
+ - application/json;charset=UTF-8
25
+ Date:
26
+ - Mon, 01 Sep 2014 06:49:28 GMT
27
+ Server:
28
+ - Apache
29
+ Vary:
30
+ - Accept-Encoding
31
+ X-Frame-Options:
32
+ - SAMEORIGIN
33
+ X-Mashery-Responder:
34
+ - prod-j-worker-us-east-1d-44.mashery.com
35
+ Content-Length:
36
+ - '272'
37
+ Connection:
38
+ - keep-alive
39
+ body:
40
+ encoding: UTF-8
41
+ string: '{"races":[{"id":6,"mask":32,"side":"horde","name":"Tauren"},{"id":5,"mask":16,"side":"horde","name":"Undead"},{"id":2,"mask":2,"side":"horde","name":"Orc"},{"id":7,"mask":64,"side":"alliance","name":"Gnome"},{"id":9,"mask":256,"side":"horde","name":"Goblin"},{"id":1,"mask":1,"side":"alliance","name":"Human"},{"id":8,"mask":128,"side":"horde","name":"Troll"},{"id":24,"mask":8388608,"side":"neutral","name":"Pandaren"},{"id":11,"mask":1024,"side":"alliance","name":"Draenei"},{"id":22,"mask":2097152,"side":"alliance","name":"Worgen"},{"id":10,"mask":512,"side":"horde","name":"Blood
42
+ Elf"},{"id":4,"mask":8,"side":"alliance","name":"Night Elf"},{"id":3,"mask":4,"side":"alliance","name":"Dwarf"},{"id":25,"mask":16777216,"side":"alliance","name":"Pandaren"},{"id":26,"mask":33554432,"side":"horde","name":"Pandaren"}]}'
43
+ http_version:
44
+ recorded_at: Mon, 01 Sep 2014 06:49:28 GMT
45
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,34 @@
1
+ require "bnet/version"
2
+ require 'open-uri'
3
+ require 'json'
4
+
5
+ require "bnet/configuration"
6
+
7
+ module Bnet
8
+ def self.configuration
9
+ @configuration ||= Bnet::Configuration.new
10
+ end
11
+
12
+ def self.configuration=(configuration)
13
+ @configuration = configuration
14
+ end
15
+ end
16
+
17
+ require "bnet/api"
18
+ require "bnet/bnet_resource"
19
+ require 'bnet/account'
20
+ require 'bnet/diablo3'
21
+ require 'bnet/diablo3/career'
22
+ require 'bnet/diablo3/hero'
23
+ require 'bnet/diablo3/skill'
24
+ # require 'bnet/community'
25
+ require 'bnet/starcraft2'
26
+ require 'bnet/starcraft2/profile'
27
+ require 'bnet/wow'
28
+ require 'bnet/wow/data'
29
+ require 'bnet/wow/character'
30
+
31
+ # Separate gem for rails...
32
+ # require 'bnet/rails' if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 3
33
+ # or as a railtie...
34
+ # require 'bnet/railtie' if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 3
@@ -0,0 +1,4 @@
1
+ module Bnet
2
+ class Account < Bnet::API
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ module Bnet
2
+ class API
3
+ # FIXME : get the API to append the :key param to the end of each 'get' call
4
+ attr_accessor :region
5
+
6
+ def initialize args
7
+ args.each do |k,v|
8
+ instance_variable_set("@#{k}", v) unless v.nil?
9
+ end
10
+ end
11
+
12
+ def url
13
+ "https://#{region}.api.battle.net/"
14
+ end
15
+
16
+ def self.valid_call?(status, response)
17
+ status == ['200', 'OK'] && response["code"] != 'NOTFOUND'
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ class Bnet::BnetResource
2
+ def initialize args = {}
3
+ args.each do |k,v|
4
+ instance_variable_set("@#{k}", v) unless v.nil?
5
+ end
6
+ end
7
+
8
+ def self.from_api(raw_response)
9
+ new_hash = {}
10
+ params_mapping.each do |old_key, new_key|
11
+ if raw_response.has_key?(old_key)
12
+ new_hash[new_key] = raw_response[old_key]
13
+ end
14
+ end
15
+
16
+ bnet_resource = self.new(new_hash)
17
+ end
18
+
19
+ private
20
+
21
+ def self.params_mapping
22
+ self::PARAMS_MAPPING
23
+ end
24
+
25
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module Bnet
3
+ module Client
4
+
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ class Bnet::Configuration
2
+ attr_accessor :api_key
3
+
4
+ def initialize
5
+ @api_key = {}
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Bnet
2
+ class Diablo3 < Bnet::API
3
+ attr_accessor
4
+
5
+ def url
6
+ super + "d3/"
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,91 @@
1
+ class Bnet::Diablo3::Career < Bnet::BnetResource
2
+
3
+ attr_accessor :heroes, :last_hero_played, :last_updated, :kills, :time_played,
4
+ :fallen_heroes, :paragon_level, :paragon_level_hardcore, :battle_tag,
5
+ :progression, :region
6
+
7
+ PARAMS_MAPPING = {
8
+ "lastHeroPlayed" => :last_hero_played,
9
+ "lastUpdated" => :last_updated,
10
+ "kills" => :kills,
11
+ "timePlayed" => :time_played,
12
+ "fallenHeroes" => :fallen_heroes,
13
+ "paragonLevel" => :paragon_level,
14
+ "paragonLevelHardcore" => :paragon_level_hardcore,
15
+ "battleTag" => :battle_tag,
16
+ "progression" => :progression
17
+ }
18
+
19
+ def battle_tag
20
+ @battle_tag.gsub('-', '#')
21
+ end
22
+
23
+ # Perform a query for the Diablo 3 character profile.
24
+ #
25
+ # Arguments
26
+ # Required
27
+ # :battle_tag - Player Battletag (ex. PlayerOne#1309)
28
+ # :region - Account region (ex. 'us')
29
+ # Optional
30
+ # :locale - String locale (default: 'en_US')
31
+ # :api_key - String API key
32
+ #
33
+ # Example
34
+ #
35
+ # Bnet::Diablo3::Career.find(battle_tag: 'PlayerOne#1309', region: 'us')
36
+ #
37
+ # Returns a Career object with the following attributes
38
+ #
39
+ # :heroes, :last_hero_played, :last_updated, :kills, :time_played,
40
+ # :fallen_heroes, :paragon_level, :paragon_level_hardcore, :battle_tag,
41
+ # :progression, :region
42
+ #
43
+ # Note : Autoloads the associated hero records from the Hero API as well
44
+ def self.find args
45
+ battle_tag = args[:battle_tag].gsub('#', '-')
46
+ region = args[:region]
47
+ api_key = args[:api_key] || Bnet.configuration.api_key
48
+ locale = args[:locale] || 'en_US'
49
+
50
+ base_api = Bnet::Diablo3.new(region: region)
51
+ call_url = base_api.url + "profile/#{battle_tag}/?apikey=#{api_key}&locale=#{locale}"
52
+
53
+ # NOTE common tasks below - marker for easier method extraction
54
+ response = JSON.parse( URI.parse(call_url).read )
55
+
56
+ data = open(call_url)
57
+ raw_response = JSON.parse(data.read)
58
+
59
+ if Bnet::API.valid_call?(data.status, raw_response)
60
+ career = from_api(raw_response)
61
+ else
62
+ career = nil
63
+ end
64
+ # NOTE end of common tasks
65
+
66
+ if career
67
+ career.battle_tag = battle_tag
68
+ career.region = region
69
+
70
+ # Association tasks (TODO: convert to hook)
71
+ if raw_response["heroes"]
72
+ heroes = response["heroes"].collect do |raw_hero_attrs|
73
+ hero = Bnet::Diablo3::Hero.from_api(raw_hero_attrs)
74
+ hero.career = career
75
+ hero.battle_tag = career.battle_tag
76
+ hero.region = career.region
77
+ hero.reload
78
+ hero
79
+ end
80
+
81
+ career.heroes = heroes
82
+ end
83
+ # End of association tasks
84
+
85
+ end
86
+
87
+ return career
88
+ end
89
+
90
+
91
+ end
@@ -0,0 +1,131 @@
1
+ class Bnet::Diablo3::Hero < Bnet::BnetResource
2
+
3
+ attr_accessor :paragon_level, :seasonal, :name, :hero_id,
4
+ :level, :hardcore, :gender, :dead, :hero_class, :last_update,
5
+ :active_skills, :passive_skills, :region, :battle_tag, :career
6
+
7
+ PARAMS_MAPPING = {
8
+ "paragonLevel" => :paragon_level,
9
+ "seasonal" => :seasonal,
10
+ "name" => :name,
11
+ "id" => :hero_id,
12
+ "level" => :level,
13
+ "hardcore" => :hardcore,
14
+ "gender" => :gender,
15
+ "dead" => :dead,
16
+ "class" => :hero_class,
17
+ "last-updated" => :last_updated
18
+ }
19
+
20
+
21
+ # TODO:Implement
22
+ # def career
23
+ # @career = #DO
24
+ # end
25
+
26
+ def active_skills
27
+ @active_skills ||= []
28
+ end
29
+
30
+ def passive_skills
31
+ @passive_skills ||= []
32
+ end
33
+
34
+ def battle_tag
35
+ @battle_tag.gsub("-", "#")
36
+ end
37
+
38
+ #TODO Extract finder_args to a method then move this `reload ` method to super
39
+ #class
40
+ def reload
41
+ finder_args = {battle_tag: battle_tag, region: region, hero_id: hero_id}
42
+ fetched_record = self.class.find(finder_args)
43
+ fetched_record.instance_variables.each do |ivar|
44
+ self.instance_variable_set(ivar, fetched_record.instance_variable_get(ivar))
45
+ end
46
+ end
47
+
48
+ # Perform a query for the D3 career's hero
49
+ #
50
+ # Arguments
51
+ # Required
52
+ # :battle_tag - Player Battletag (ex. PlayerOne#1309)
53
+ # :region - Account region (ex. 'us')
54
+ # :hero_id - You can get this from an existing Career object
55
+ # or from the website url when you view a hero
56
+ # Optional
57
+ # :locale - String locale (default: 'en_US')
58
+ # :api_key - String API key
59
+ #
60
+ # Example
61
+ #
62
+ # Bnet::Diablo3::Hero.find(battle_tag: 'PlayerOne-1309', region: 'us', hero_id: 1304986)
63
+ #
64
+ # Returns a Hero object with the following attributes
65
+ #
66
+ # :paragon_level, :seasonal, :name, :hero_id,
67
+ # :level, :hardcore, :gender, :dead, :hero_class, :last_update,
68
+ # :active_skills, :passive_skills, :region, :battle_tag, :career
69
+ def self.find args
70
+ battle_tag = args[:battle_tag]
71
+ region = args[:region]
72
+ hero_id = args[:hero_id]
73
+ locale = args[:locale] || 'en_US'
74
+ api_key = args[:api_key] || Bnet.configuration.api_key
75
+
76
+ if battle_tag
77
+ battle_tag.gsub!('#', '-')
78
+ end
79
+
80
+ base_api = Bnet::Diablo3.new(region: region)
81
+ call_url = base_api.url + "profile/#{battle_tag}/hero/#{hero_id}?apikey=#{api_key}&locale=#{locale}"
82
+
83
+ begin
84
+ data = open(call_url)
85
+ raw_response = JSON.parse(data.read)
86
+
87
+ if Bnet::API.valid_call?(data.status, raw_response)
88
+ bnet_object = from_api(raw_response)
89
+ else
90
+ bnet_object = nil
91
+ end
92
+
93
+ rescue OpenURI::HTTPError => e
94
+ bnet_object = nil
95
+ end
96
+
97
+ return bnet_object
98
+ end
99
+
100
+ # Create an instance by passing in the args from the response
101
+ def self.from_api(response)
102
+ bnet_resource = super(response)
103
+
104
+ if bnet_resource && response["skills"]
105
+ bnet_resource.active_skills = response["skills"]["active"].collect do |active|
106
+
107
+ skill = Bnet::Diablo3::Skill.new
108
+ if active["skill"]
109
+ skill.name = active["skill"]["name"]
110
+ end
111
+ if active["rune"]
112
+ skill.rune = active["rune"]["name"]
113
+ end
114
+
115
+ skill
116
+
117
+ end
118
+
119
+ bnet_resource.passive_skills = response["skills"]["passive"].collect do |passive|
120
+ skill = Bnet::Diablo3::Skill.new
121
+ if passive["skill"]
122
+ skill.name = passive["skill"]["name"]
123
+ end
124
+ skill
125
+ end
126
+ end
127
+
128
+ bnet_resource
129
+ end
130
+
131
+ end