ruby-iactionable 0.0.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.
- data/.gitignore +4 -0
- data/.rvmrc +3 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +43 -0
- data/README.md +49 -0
- data/Rakefile +1 -0
- data/lib/iactionable/api.rb +170 -0
- data/lib/iactionable/connection.rb +114 -0
- data/lib/iactionable/error.rb +17 -0
- data/lib/iactionable/objects/achievement.rb +29 -0
- data/lib/iactionable/objects/awardable.rb +50 -0
- data/lib/iactionable/objects/challenge.rb +27 -0
- data/lib/iactionable/objects/goal.rb +30 -0
- data/lib/iactionable/objects/i_actionable_object.rb +36 -0
- data/lib/iactionable/objects/identifier.rb +17 -0
- data/lib/iactionable/objects/leaderboard.rb +15 -0
- data/lib/iactionable/objects/leaderboard_report.rb +30 -0
- data/lib/iactionable/objects/level.rb +24 -0
- data/lib/iactionable/objects/level_type.rb +15 -0
- data/lib/iactionable/objects/point_type.rb +15 -0
- data/lib/iactionable/objects/profile_achievements.rb +20 -0
- data/lib/iactionable/objects/profile_challenges.rb +20 -0
- data/lib/iactionable/objects/profile_goals.rb +20 -0
- data/lib/iactionable/objects/profile_level.rb +20 -0
- data/lib/iactionable/objects/profile_notifications.rb +29 -0
- data/lib/iactionable/objects/profile_points.rb +29 -0
- data/lib/iactionable/objects/profile_summary.rb +32 -0
- data/lib/iactionable/objects/progress.rb +46 -0
- data/lib/iactionable/objects.rb +27 -0
- data/lib/iactionable/settings.rb +30 -0
- data/lib/iactionable/version.rb +3 -0
- data/lib/iactionable.rb +9 -0
- data/ruby_iactionable.gemspec +28 -0
- data/spec/api/get_achievements_api_response_spec.rb +46 -0
- data/spec/api/get_challenges_api_response_spec.rb +42 -0
- data/spec/api/get_goals_api_response_spec.rb +46 -0
- data/spec/api/get_leaderboard_api_response_spec.rb +76 -0
- data/spec/api/get_profile_achievements_api_response_spec.rb +99 -0
- data/spec/api/get_profile_api_response_spec.rb +103 -0
- data/spec/api/get_profile_challenges_api_response_spec.rb +85 -0
- data/spec/api/get_profile_goals_api_response_spec.rb +89 -0
- data/spec/api/get_profile_notifications_api_response_spec.rb +75 -0
- data/spec/api/get_profile_points_api_response_spec.rb +67 -0
- data/spec/api_spec.rb +314 -0
- data/spec/connection_spec.rb +111 -0
- data/spec/settings_spec.rb +52 -0
- data/spec/spec_helper.rb +1 -0
- metadata +163 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
Ruby IActionable (0.0.1)
|
5
|
+
activesupport (>= 3.0.0)
|
6
|
+
faraday
|
7
|
+
faraday-stack
|
8
|
+
rake
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (3.2.1)
|
14
|
+
i18n (~> 0.6)
|
15
|
+
multi_json (~> 1.0)
|
16
|
+
addressable (2.2.6)
|
17
|
+
diff-lcs (1.1.3)
|
18
|
+
faraday (0.7.6)
|
19
|
+
addressable (~> 2.2)
|
20
|
+
multipart-post (~> 1.1)
|
21
|
+
rack (~> 1.1)
|
22
|
+
faraday-stack (0.1.5)
|
23
|
+
faraday (>= 0.6, < 0.8)
|
24
|
+
i18n (0.6.0)
|
25
|
+
multi_json (1.0.4)
|
26
|
+
multipart-post (1.1.4)
|
27
|
+
rack (1.4.1)
|
28
|
+
rake (0.9.2.2)
|
29
|
+
rspec (2.7.0)
|
30
|
+
rspec-core (~> 2.7.0)
|
31
|
+
rspec-expectations (~> 2.7.0)
|
32
|
+
rspec-mocks (~> 2.7.0)
|
33
|
+
rspec-core (2.7.1)
|
34
|
+
rspec-expectations (2.7.0)
|
35
|
+
diff-lcs (~> 1.1.2)
|
36
|
+
rspec-mocks (2.7.0)
|
37
|
+
|
38
|
+
PLATFORMS
|
39
|
+
ruby
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
Ruby IActionable!
|
43
|
+
rspec (>= 2.6)
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Overview #
|
2
|
+
|
3
|
+
Ruby IActionable is a straightforward wrapper for IActionable's restful API. The JSON-encoded responses from IActionable are wrapped in objects that provide a few extra functions here and there, but are mostly just a representation of the API response.
|
4
|
+
|
5
|
+
# How To Use #
|
6
|
+
|
7
|
+
## Installation ##
|
8
|
+
|
9
|
+
gem install ruby-iactionable
|
10
|
+
|
11
|
+
## IRB ##
|
12
|
+
|
13
|
+
require 'iactionable'
|
14
|
+
|
15
|
+
## Bundler ##
|
16
|
+
|
17
|
+
gem 'ruby-iactionable', :require => 'iactionable'
|
18
|
+
|
19
|
+
## API Credentials And Initialization ##
|
20
|
+
|
21
|
+
Before the API wrapper can be instantiated or used it must be pre-initialized with your IActionable credentials and version number (IActionable supports older versions but recommends staying up to date):
|
22
|
+
|
23
|
+
IActionable::Api.init_settings( :app_key => "12345",
|
24
|
+
:api_key => "abcde",
|
25
|
+
:version => 3 )
|
26
|
+
@api = IActionable::Api.new
|
27
|
+
|
28
|
+
The responses for each of the endpoints of IActionable's API are described through example by [their documentation](http://www.iactionable.com/api/). Here is an example of the response from a [profile summary](http://iactionable.com/api/profiles/#getprofilesummary) returned as an object by the wrapper.
|
29
|
+
|
30
|
+
profile_summary = @api.get_profile_summary("user", "username", "zortnac", 10)
|
31
|
+
profile_summary.display_name # => "Chris Eberz"
|
32
|
+
profile_summary.identifiers.first # => instance of IActionable::Objects::Identifier
|
33
|
+
profile_summary.identifiers.first.id_type # => "username"
|
34
|
+
profile_summary.identifiers.first.id # => "zortnac"
|
35
|
+
|
36
|
+
Each object can be dumped back in to its original form of arrays and key/value pairs:
|
37
|
+
|
38
|
+
profile_summary.to_hash # => { "DisplayName" => "Chris Eberz", "Identifiers" => [ {"ID" => "zortnac", "IDType" => "username", ...} ] ... }
|
39
|
+
# (not shown in entirety)
|
40
|
+
|
41
|
+
----------------
|
42
|
+
|
43
|
+
## IActionable ##
|
44
|
+
|
45
|
+
[Visit their website!](http://www.iactionable.com)
|
46
|
+
|
47
|
+
## Author ##
|
48
|
+
|
49
|
+
Christopher Eberz; chris@chriseberz.com; @zortnac
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'iactionable/connection.rb'
|
2
|
+
require 'iactionable/settings.rb'
|
3
|
+
require 'iactionable/objects.rb'
|
4
|
+
|
5
|
+
module IActionable
|
6
|
+
|
7
|
+
class Api
|
8
|
+
attr :connection
|
9
|
+
@@settings = nil
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
if @@settings
|
13
|
+
@connection = IActionable::Connection.new(@@settings)
|
14
|
+
else
|
15
|
+
raise IActionable::ConfigError.new("IActionable::Api cannot be initialized without credentials being set in IActionable::Api.init_settings()")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.init_settings(values)
|
20
|
+
@@settings = IActionable::Settings.new(values)
|
21
|
+
rescue IActionable::ConfigError => e
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.settings
|
26
|
+
@@settings
|
27
|
+
end
|
28
|
+
|
29
|
+
# =================
|
30
|
+
# = Event Logging =
|
31
|
+
# =================
|
32
|
+
|
33
|
+
def log_event(profile_type, id_type, id, event_key, event_attrs = {})
|
34
|
+
response = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/events/#{event_key}").with_params(event_attrs).post
|
35
|
+
end
|
36
|
+
|
37
|
+
# =====================
|
38
|
+
# = Profile API calls =
|
39
|
+
# =====================
|
40
|
+
|
41
|
+
def get_profile_summary(profile_type, id_type, id, achievement_count = nil)
|
42
|
+
request = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}")
|
43
|
+
request.with_params(:achievementCount => achievement_count) unless achievement_count.blank?
|
44
|
+
response = request.get
|
45
|
+
IActionable::Objects::ProfileSummary.new(response)
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_profile(profile_type, id_type, id, display_name = nil)
|
49
|
+
request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}")
|
50
|
+
request.with_params(:displayName => display_name) unless display_name.blank?
|
51
|
+
request.post
|
52
|
+
end
|
53
|
+
alias_method :update_profile, :create_profile
|
54
|
+
|
55
|
+
def add_profile_identifier(profile_type, id_type, id, alt_id_type, alt_id)
|
56
|
+
@connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/identifiers/#{alt_id_type}/#{alt_id}").post
|
57
|
+
end
|
58
|
+
|
59
|
+
# ====================
|
60
|
+
# = Points API calls =
|
61
|
+
# ====================
|
62
|
+
|
63
|
+
def get_profile_points(profile_type, id_type, id, point_type)
|
64
|
+
response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").get
|
65
|
+
IActionable::Objects::ProfilePoints.new(response)
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_profile_points(profile_type, id_type, id, point_type, amount, reason = nil)
|
69
|
+
request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").with_params(:value => amount)
|
70
|
+
request.with_params(:description => reason) unless reason.blank?
|
71
|
+
response = request.post
|
72
|
+
IActionable::Objects::ProfilePoints.new(response)
|
73
|
+
end
|
74
|
+
|
75
|
+
# =========================
|
76
|
+
# = Achievement API calls =
|
77
|
+
# =========================
|
78
|
+
|
79
|
+
def get_profile_achievements(profile_type, id_type, id, filter_type = nil)
|
80
|
+
request = @connection.request.with_app_key
|
81
|
+
case filter_type
|
82
|
+
when :completed
|
83
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Completed")
|
84
|
+
when :available
|
85
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Available")
|
86
|
+
else
|
87
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/achievements")
|
88
|
+
end
|
89
|
+
IActionable::Objects::ProfileAchievements.new(request.get)
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_achievements()
|
93
|
+
response = @connection.request.with_app_key.to("/achievements").get
|
94
|
+
response.map{|achievement_json| IActionable::Objects::Achievement.new(achievement_json)}
|
95
|
+
rescue NoMethodError => e
|
96
|
+
[]
|
97
|
+
end
|
98
|
+
|
99
|
+
# ========================
|
100
|
+
# = Challenges API calls =
|
101
|
+
# ========================
|
102
|
+
|
103
|
+
def get_profile_challenges(profile_type, id_type, id, filter_type = nil)
|
104
|
+
request = @connection.request.with_app_key
|
105
|
+
case filter_type
|
106
|
+
when :completed
|
107
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Completed")
|
108
|
+
when :available
|
109
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Available")
|
110
|
+
else
|
111
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/challenges")
|
112
|
+
end
|
113
|
+
IActionable::Objects::ProfileChallenges.new(request.get)
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_challenges()
|
117
|
+
response = @connection.request.with_app_key.to("/challenges").get
|
118
|
+
response.map{|challenge_json| IActionable::Objects::Challenge.new(challenge_json)}
|
119
|
+
rescue NoMethodError => e
|
120
|
+
[]
|
121
|
+
end
|
122
|
+
|
123
|
+
# ===================
|
124
|
+
# = Goals API calls =
|
125
|
+
# ===================
|
126
|
+
|
127
|
+
def get_profile_goals(profile_type, id_type, id, filter_type = nil)
|
128
|
+
request = @connection.request.with_app_key
|
129
|
+
case filter_type
|
130
|
+
when :completed
|
131
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/goals/Completed")
|
132
|
+
when :available
|
133
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/goals/Available")
|
134
|
+
else
|
135
|
+
request.to("/#{profile_type}/#{id_type}/#{id}/goals")
|
136
|
+
end
|
137
|
+
IActionable::Objects::ProfileGoals.new(request.get)
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_goals()
|
141
|
+
response = @connection.request.with_app_key.to("/goals").get
|
142
|
+
response.map{|goal_json| IActionable::Objects::Goal.new(goal_json)}
|
143
|
+
rescue NoMethodError => e
|
144
|
+
[]
|
145
|
+
end
|
146
|
+
|
147
|
+
# =========================
|
148
|
+
# = Leaderboard API calls =
|
149
|
+
# =========================
|
150
|
+
|
151
|
+
def get_leaderboard(profile_type, point_type, leaderboard, page_number=nil, page_count=nil, id=nil, id_type=nil)
|
152
|
+
request = @connection.request.with_app_key.to("/#{profile_type}/leaderboards/points/#{point_type}/#{leaderboard}")
|
153
|
+
request.with_params(:pageNumber => page_number) unless page_number.blank?
|
154
|
+
request.with_params(:pageCount => page_count) unless page_count.blank?
|
155
|
+
request.with_params(:id => id) unless id.blank? || id_type.blank?
|
156
|
+
request.with_params(:idType => id_type) unless id.blank? || id_type.blank?
|
157
|
+
response = request.get
|
158
|
+
IActionable::Objects::LeaderboardReport.new(response)
|
159
|
+
end
|
160
|
+
|
161
|
+
# ===================================
|
162
|
+
# = Profile Notifications API calls =
|
163
|
+
# ===================================
|
164
|
+
|
165
|
+
def get_profile_notifications(profile_type, id_type, id)
|
166
|
+
response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/notifications").get
|
167
|
+
IActionable::Objects::ProfileNotifications.new(response)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_stack'
|
3
|
+
require 'iactionable/error'
|
4
|
+
|
5
|
+
module IActionable
|
6
|
+
class Request < Struct.new(:path, :params, :headers, :body)
|
7
|
+
attr :settings
|
8
|
+
|
9
|
+
def initialize(settings)
|
10
|
+
@settings = settings
|
11
|
+
self.path = nil
|
12
|
+
self.params = {}
|
13
|
+
self.headers = {}
|
14
|
+
self.body = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def to(path)
|
18
|
+
self.path = path unless path.nil? || path.empty?
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_api_key
|
23
|
+
(self.headers[:Authorization] = @settings.api_key) and self
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_app_key
|
27
|
+
(self.params[:appKey] = @settings.app_key) and self
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_params(params={})
|
31
|
+
self.params.merge!(params) and self
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_body(body={})
|
35
|
+
self.body.merge!(body) and self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Connection
|
40
|
+
attr :connection
|
41
|
+
attr :settings
|
42
|
+
attr :request
|
43
|
+
attr_accessor :response
|
44
|
+
|
45
|
+
def initialize(settings)
|
46
|
+
@settings = settings
|
47
|
+
|
48
|
+
@connection = Faraday.new api_url(@settings.version) do |builder|
|
49
|
+
builder.use FaradayStack::ResponseJSON, content_type: 'application/json'
|
50
|
+
builder.use Faraday::Response::RaiseError
|
51
|
+
builder.use Faraday::Adapter::NetHttp
|
52
|
+
end
|
53
|
+
|
54
|
+
@request = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def request
|
58
|
+
(@request = Request.new(@settings)) and self
|
59
|
+
end
|
60
|
+
|
61
|
+
def get(path=nil, query_params={})
|
62
|
+
@request ||= Request.new(@settings)
|
63
|
+
@request.to(path).with_params(query_params)
|
64
|
+
@response = @connection.get do |req|
|
65
|
+
req.headers.merge! @request.headers
|
66
|
+
req.url @request.path, @request.params
|
67
|
+
end
|
68
|
+
@response.body
|
69
|
+
rescue Faraday::Error::ClientError => e
|
70
|
+
handle_client_error e
|
71
|
+
ensure
|
72
|
+
@request = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def post(path=nil, query_params={}, body_params={})
|
76
|
+
@request ||= Request.new(@settings)
|
77
|
+
@request.to(path).with_params(query_params)
|
78
|
+
@response = @connection.post do |req|
|
79
|
+
req.headers.merge! @request.headers
|
80
|
+
req.url @request.path, @request.params
|
81
|
+
req.body = @request.body unless @request.body.empty?
|
82
|
+
end
|
83
|
+
@response.body
|
84
|
+
rescue Exception => e
|
85
|
+
handle_client_error e
|
86
|
+
ensure
|
87
|
+
@request = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def method_missing(symbol, *args)
|
93
|
+
@request.send(symbol, *args) and self
|
94
|
+
rescue NoMethodError => e
|
95
|
+
raise e
|
96
|
+
end
|
97
|
+
|
98
|
+
def api_url(version)
|
99
|
+
"http://api.iactionable.com/v#{version}/"
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_client_error(e)
|
103
|
+
# http://iactionable.com/api/response-codes/
|
104
|
+
case e.response[:status]
|
105
|
+
when 400
|
106
|
+
raise IActionable::Error::BadRequest.new(e.response)
|
107
|
+
when 401
|
108
|
+
raise IActionable::Error::Unauthorized.new(e.response)
|
109
|
+
when 500
|
110
|
+
raise IActionable::Error::Internal.new(e.response)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Error
|
3
|
+
class Error < StandardError
|
4
|
+
attr_accessor :response
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
@response = response
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# http://iactionable.com/api/response-codes/
|
13
|
+
class BadRequest < Error; end
|
14
|
+
class Unauthorized < Error; end
|
15
|
+
class Internal < Error; end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class Achievement < IActionableObject
|
4
|
+
attr_accessor :key
|
5
|
+
attr_accessor :description
|
6
|
+
attr_accessor :image_url
|
7
|
+
attr_accessor :name
|
8
|
+
|
9
|
+
def initialize(key_values={})
|
10
|
+
initialize_awardable(key_values)
|
11
|
+
super(key_values)
|
12
|
+
end
|
13
|
+
|
14
|
+
awardable
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
hash = {
|
18
|
+
"Key" => @key,
|
19
|
+
"Description" => @description,
|
20
|
+
"ImageURL" => @image_url,
|
21
|
+
"Name" => @name
|
22
|
+
}
|
23
|
+
hash.merge!(awardable_hash) unless @progress.empty?
|
24
|
+
hash.delete("AwardDate") if @award_date.nil?
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
module Awardable
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def awardable
|
10
|
+
attr_accessor :award_date
|
11
|
+
attr_accessor :original_award_date
|
12
|
+
attr_accessor :progress
|
13
|
+
include IActionable::Objects::Awardable::InstanceMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def initialize_awardable(key_values={})
|
19
|
+
@progress = extract_many_as(key_values, "Progress", IActionable::Objects::Progress)
|
20
|
+
# convert the miliseconds within the date string to seconds (per ruby)
|
21
|
+
# "/Date(1275706032317-0600)/" => "1275706032-0600"
|
22
|
+
@original_award_date = @award_date = key_values.delete("AwardDate")
|
23
|
+
@award_date = IActionableObject.timestamp_to_seconds(@award_date) unless @award_date.blank?
|
24
|
+
end
|
25
|
+
|
26
|
+
def complete?
|
27
|
+
@progress.any? && @progress.all?
|
28
|
+
end
|
29
|
+
|
30
|
+
def percent_complete
|
31
|
+
Integer(Float(@progress.select{|p| p.complete?}.size) / @progress.size * 100)
|
32
|
+
rescue TypeError => e
|
33
|
+
0
|
34
|
+
end
|
35
|
+
|
36
|
+
def awarded_on
|
37
|
+
# bug in ruby 1.9.2 where Time.strptime does not support seconds-since-epoch format, but Date.strptime does, so we'll use that for now
|
38
|
+
Date.strptime(@award_date, "%s%z").to_time unless @award_date.blank?
|
39
|
+
end
|
40
|
+
|
41
|
+
def awardable_hash
|
42
|
+
{
|
43
|
+
"AwardDate" => @original_award_date,
|
44
|
+
"Progress" => @progress.map{|prog| prog.to_hash}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class Challenge < IActionableObject
|
4
|
+
awardable
|
5
|
+
|
6
|
+
attr_accessor :key
|
7
|
+
attr_accessor :description
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
def initialize(key_values={})
|
11
|
+
initialize_awardable(key_values)
|
12
|
+
super(key_values)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
hash = {
|
17
|
+
"Key" => @key,
|
18
|
+
"Description" => @description,
|
19
|
+
"Name" => @name
|
20
|
+
}
|
21
|
+
hash.merge!(awardable_hash) unless @progress.empty?
|
22
|
+
hash.delete("AwardDate") if @award_date.nil?
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class Goal < IActionableObject
|
4
|
+
awardable
|
5
|
+
|
6
|
+
attr_accessor :key
|
7
|
+
attr_accessor :description
|
8
|
+
attr_accessor :name
|
9
|
+
attr_accessor :interval
|
10
|
+
|
11
|
+
def initialize(key_values={})
|
12
|
+
initialize_awardable(key_values)
|
13
|
+
super(key_values)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
hash = {
|
18
|
+
"Key" => @key,
|
19
|
+
"Description" => @description,
|
20
|
+
"Name" => @name,
|
21
|
+
"Interval" => @interval
|
22
|
+
}
|
23
|
+
hash.merge!(awardable_hash) unless @progress.empty?
|
24
|
+
hash.delete("AwardDate") if @award_date.nil?
|
25
|
+
hash.delete("Interval") if @interval.nil?
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class IActionableObject
|
4
|
+
def initialize(key_values={})
|
5
|
+
key_values.each_pair do |key, value|
|
6
|
+
instance_variable_set "@#{key.camelize.underscore}".to_sym, value
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.timestamp_regexp
|
11
|
+
/\/Date\((\d+)((\-|\+)\d{4})\)\//
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.timestamp_to_seconds(timestamp)
|
15
|
+
milliseconds = timestamp[timestamp_regexp, 1]
|
16
|
+
tz = timestamp[timestamp_regexp, 2]
|
17
|
+
"#{Integer(milliseconds)/1000}#{tz}"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def extract_many_as(key_values, field, klass)
|
23
|
+
if key_values.fetch(field, nil).respond_to?(:inject)
|
24
|
+
loaded = []
|
25
|
+
content = key_values.delete(field)
|
26
|
+
content.each do |c|
|
27
|
+
loaded << klass.new(c)
|
28
|
+
end
|
29
|
+
loaded
|
30
|
+
else
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class Identifier < IActionableObject
|
4
|
+
attr_accessor :id
|
5
|
+
attr_accessor :id_hash
|
6
|
+
attr_accessor :id_type
|
7
|
+
|
8
|
+
def to_hash
|
9
|
+
{
|
10
|
+
"ID" => @id,
|
11
|
+
"IDHash" => @id_hash,
|
12
|
+
"IDType" => @id_type
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class LeaderboardReport < IActionableObject
|
4
|
+
attr_accessor :page_count
|
5
|
+
attr_accessor :page_number
|
6
|
+
attr_accessor :total_count
|
7
|
+
attr_accessor :leaderboard
|
8
|
+
attr_accessor :point_type
|
9
|
+
attr_accessor :profiles
|
10
|
+
|
11
|
+
def initialize(key_values={})
|
12
|
+
@leaderboard = IActionable::Objects::PointType.new(key_values.delete("Leaderboard"))
|
13
|
+
@point_type = IActionable::Objects::PointType.new(key_values.delete("PointType"))
|
14
|
+
@profiles = extract_many_as(key_values, "Profiles", IActionable::Objects::ProfileSummary)
|
15
|
+
super(key_values)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_hash
|
19
|
+
{
|
20
|
+
"PageCount" => @page_count,
|
21
|
+
"PageNumber" => @page_number,
|
22
|
+
"TotalCount" => @total_count,
|
23
|
+
"Leaderboard" => @leaderboard.to_hash,
|
24
|
+
"PointType" => @point_type.to_hash,
|
25
|
+
"Profiles" => @profiles.map{|profile| profile.to_hash}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module IActionable
|
2
|
+
module Objects
|
3
|
+
class Level < IActionableObject
|
4
|
+
attr_accessor :name
|
5
|
+
attr_accessor :number
|
6
|
+
attr_accessor :required_points
|
7
|
+
attr_accessor :level_type
|
8
|
+
|
9
|
+
def initialize(key_values={})
|
10
|
+
@level_type = IActionable::Objects::LevelType.new(key_values.delete("LevelType"))
|
11
|
+
super(key_values)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
{
|
16
|
+
"Name" => @name,
|
17
|
+
"Number" => @number,
|
18
|
+
"RequiredPoints" => @required_points,
|
19
|
+
"LevelType" => @level_type.to_hash
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|