gamifier 1.0.3

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.
Files changed (41) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +60 -0
  5. data/Rakefile +2 -0
  6. data/examples/dev.rb +186 -0
  7. data/examples/preprod.rb +218 -0
  8. data/gamifier.gemspec +24 -0
  9. data/lib/gamifier/collection.rb +26 -0
  10. data/lib/gamifier/dsl/network.rb +33 -0
  11. data/lib/gamifier/dsl/site.rb +134 -0
  12. data/lib/gamifier/dsl.rb +24 -0
  13. data/lib/gamifier/engine.rb +84 -0
  14. data/lib/gamifier/errors.rb +6 -0
  15. data/lib/gamifier/model.rb +212 -0
  16. data/lib/gamifier/models/activity.rb +8 -0
  17. data/lib/gamifier/models/activity_definition.rb +6 -0
  18. data/lib/gamifier/models/group.rb +6 -0
  19. data/lib/gamifier/models/player.rb +20 -0
  20. data/lib/gamifier/models/reward.rb +6 -0
  21. data/lib/gamifier/models/reward_definition.rb +14 -0
  22. data/lib/gamifier/models/site.rb +6 -0
  23. data/lib/gamifier/models/track.rb +6 -0
  24. data/lib/gamifier/models/unit.rb +16 -0
  25. data/lib/gamifier/models/user.rb +6 -0
  26. data/lib/gamifier/version.rb +3 -0
  27. data/lib/gamifier.rb +76 -0
  28. data/spec/integration/dsl_integration_spec.rb +76 -0
  29. data/spec/integration/player_integration_spec.rb +41 -0
  30. data/spec/integration/user_integration_spec.rb +19 -0
  31. data/spec/spec_helper.rb +7 -0
  32. data/spec/spec_integration_helper.rb +51 -0
  33. data/spec/unit/collection_spec.rb +21 -0
  34. data/spec/unit/dsl/network_spec.rb +34 -0
  35. data/spec/unit/dsl/site_spec.rb +54 -0
  36. data/spec/unit/dsl_spec.rb +9 -0
  37. data/spec/unit/engine_spec.rb +135 -0
  38. data/spec/unit/gamifier_spec.rb +60 -0
  39. data/spec/unit/model_spec.rb +182 -0
  40. data/spec/unit/models/player_spec.rb +40 -0
  41. metadata +179 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gamifier.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Cyril Rohr
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Gamifier
2
+
3
+ This gem abstracts the Badgeville API behind high level concepts such as
4
+ user, player, activities, rewards, etc.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'gamifier'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install gamifier
19
+
20
+ ## Usage
21
+
22
+ Configure Gamifier with the right parameter for the API you're using:
23
+
24
+ Gamifier.set :key => "1234", :uri => "http://sandbox.v2.badgeville.com/api/berlin/"
25
+
26
+ Then here is an example usage to credit an existing player:
27
+
28
+ Gamifier.engine do |engine|
29
+ player = engine.players.find_by_site_and_email('my-site.com', '1234@dimelo-badges.com')
30
+ player.credit('visit', :url => "http://server.ltd/page.html", :other_key => "value")
31
+ end
32
+
33
+ See the `examples/` directory for examples on how to use the DSL to
34
+ declare activities, rewards and missions, and you can execute a DSL as
35
+ follows:
36
+
37
+ BADGEVILLE_KEY=xzy bundle exec ruby -I lib examples/dev.rb
38
+
39
+ ## Tests
40
+
41
+ Run the unit tests with:
42
+
43
+ bundle exec spec spec/unit
44
+
45
+ Run the integration tests as follows:
46
+
47
+ BADGEVILLE_KEY=1234 bundle exec spec spec/integration
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
56
+
57
+
58
+ ## Authors
59
+
60
+ * Cyril Rohr <cyril.rohr@gmail.com>
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/examples/dev.rb ADDED
@@ -0,0 +1,186 @@
1
+ require 'gamifier'
2
+ require 'json'
3
+
4
+ Gamifier.set :uri => "http://sandbox.v2.badgeville.com/api/berlin/", :key => ENV.fetch('BADGEVILLE_KEY')
5
+ Gamifier.logger.level = Logger::DEBUG
6
+
7
+ network = Gamifier.dsl do
8
+ site 'dev2.domain-test.crohr.me' do |site|
9
+ set :url, 'dev2.domain-test.crohr.me'
10
+
11
+ unit :karma do
12
+ set :label, 'Karma'
13
+ set :abbreviation, 'kar'
14
+ end
15
+
16
+ behavior 'visit' do
17
+ set :description, "visit"
18
+ set :selector, {
19
+ :verb => 'visit'
20
+ }
21
+
22
+ set :enable_count_limiting, false
23
+ set :enable_rate_limiting, false
24
+
25
+ set :hide_in_widgets, true
26
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
27
+ end
28
+
29
+ behavior 'signin' do
30
+ set :description, "signin"
31
+ set :selector, {
32
+ :verb => 'signin'
33
+ }
34
+
35
+ set :enable_count_limiting, false
36
+ set :enable_rate_limiting, true
37
+ set :bucket_max_capacity, 2
38
+ set :bucket_drain_rate, bucket_max_capacity/1.5
39
+
40
+ set :hide_in_widgets, false
41
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
42
+ end
43
+
44
+ behavior 'comment' do
45
+ set :description, "new comment"
46
+ set :selector, {
47
+ :verb => 'comment'
48
+ }
49
+ set :adjustment, {
50
+ :points => 1, :karma => 1
51
+ }
52
+
53
+ set :enable_count_limiting, false
54
+ # set :limit_per_player, 20
55
+
56
+ set :enable_rate_limiting, true
57
+ set :bucket_max_capacity, 2
58
+ set :bucket_drain_rate, bucket_max_capacity/1.5
59
+
60
+ set :hide_in_widgets, false
61
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
62
+ end
63
+
64
+ # behavior 'comment_databases' do
65
+ # set :description, "new comment in category databases"
66
+ # set :selector, {
67
+ # :verb => 'comment',
68
+ # :category_slug => 'databases'
69
+ # }
70
+ # set :adjustment, {
71
+ # :points => 1, :karma => 1
72
+ # }
73
+ #
74
+ # set :enable_count_limiting, true
75
+ # set :limit_per_player, 10
76
+ # set :limit_field_scope, 'category_id'
77
+ #
78
+ # set :enable_rate_limiting, true
79
+ # set :bucket_max_capacity, 2
80
+ # set :bucket_drain_rate, bucket_max_capacity/1.5
81
+ #
82
+ # set :hide_in_widgets, false
83
+ # set :icon, "http://s3.amazonaws.com/icons/icon1.png"
84
+ # end
85
+
86
+ r_member = reward 'member' do
87
+ set :reward_template, {
88
+ :message => "Congrats, you signed in for the first time!"
89
+ }
90
+ set :components, [
91
+ {:command => "count", :comparator => 1, :where => {:verb => 'signin', :player_id => "%player_id"}}
92
+ ]
93
+ set :adjustment, {
94
+ :points => 2
95
+ }
96
+ set :active, true
97
+ set :allow_duplicates, false
98
+ end
99
+
100
+ r_active_member = reward 'active member' do
101
+ set :reward_template, {
102
+ :message => "Looks like you like the site, thank you and keep up on being active on the site!"
103
+ }
104
+ set :components, [
105
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'signin', :player_id => "%player_id"}}
106
+ ]
107
+ set :adjustment, {
108
+ :points => 5
109
+ }
110
+ set :active, true
111
+ set :allow_duplicates, false
112
+ end
113
+
114
+ r_commenter = reward 'commenter' do
115
+ set :reward_template, {
116
+ :message => "Congrats, you commented on something!"
117
+ }
118
+ set :components, [
119
+ {:command => "count", :comparator => 1, :where => {:verb => 'comment', :player_id => "%player_id"}}
120
+ ]
121
+ set :adjustment, {
122
+ :points => 1
123
+ }
124
+ set :active, true
125
+ set :allow_duplicates, false
126
+ end
127
+
128
+ r_active_commenter = reward 'active commenter' do
129
+ set :reward_template, {
130
+ :message => "You have commented more than 3 times in any category!"
131
+ }
132
+ set :components, [
133
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'comment', :player_id => "%player_id"}}
134
+ ]
135
+ set :adjustment, {
136
+ :points => 3
137
+ }
138
+ set :active, true
139
+ set :allow_duplicates, false
140
+ end
141
+
142
+ r_db_commenter = reward 'database commenter' do
143
+ set :reward_template, {
144
+ :message => "You have commented more than 3 times in the database category!"
145
+ }
146
+ set :components, [
147
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'comment', :player_id => "%player_id", :category_slug => "database"}}
148
+ ]
149
+ set :adjustment, {
150
+ :points => 3
151
+ }
152
+ set :active, true
153
+ set :allow_duplicates, false
154
+ end
155
+
156
+ mission 'community member' do
157
+ # allow a player to complete this mission more than once?
158
+ set :repeatable, false
159
+ set :active, true
160
+ # give points and reward upon completing mission? (This is required for track progression)
161
+ set :enable_rewards, true
162
+ # points and secondary units to award when completing a mission
163
+ set :adjustment, {
164
+ :points => 10
165
+ }
166
+ set :reward_definition_ids do [r_active_commenter._id, r_db_commenter._id] end
167
+ end
168
+ # reward 'top commenter' do
169
+ # set :reward_template, {
170
+ # :message => "Congrats!"
171
+ # }
172
+ # set :components, [
173
+ # {:command => "count", :comparator => 1, :where => {:verb => 'comment', :player_id => "%player_id"}},
174
+ # # the first player who performs at least twice the 'new_question' behaviour
175
+ # {:command => "count", :comparator => {"$gt" => 2}, :where => {:verb => 'new_question', :site_id => "%site_id"}}
176
+ # ]
177
+ # set :adjustment, {
178
+ # :points => 5
179
+ # }
180
+ # set :active, true
181
+ # set :allow_duplicates, false
182
+ # end
183
+ end
184
+ end
185
+
186
+ network.save!
@@ -0,0 +1,218 @@
1
+ require 'gamifier'
2
+ require 'json'
3
+
4
+ Gamifier.set :uri => "http://sandbox.v2.badgeville.com/api/berlin/", :key => ENV.fetch('BADGEVILLE_KEY')
5
+ Gamifier.logger.level = Logger::INFO
6
+
7
+ network = Gamifier.dsl do
8
+ site 'preprod.domain-test.crohr.me' do
9
+ set :url, 'preprod.domain-test.answers.crohr.me'
10
+
11
+ unit :karma do
12
+ set :label, 'Karma'
13
+ set :abbreviation, 'kar'
14
+ end
15
+
16
+ behavior 'visit' do
17
+ set :description, "visit"
18
+ set :selector, {
19
+ :verb => 'visit'
20
+ }
21
+
22
+ set :enable_count_limiting, false
23
+ set :enable_rate_limiting, false
24
+
25
+ set :hide_in_widgets, true
26
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
27
+ end
28
+
29
+ behavior 'signin' do
30
+ set :description, "signin"
31
+ set :selector, {
32
+ :verb => 'signin'
33
+ }
34
+
35
+ set :enable_count_limiting, false
36
+ set :enable_rate_limiting, true
37
+ set :bucket_max_capacity, 2
38
+ set :bucket_drain_rate, bucket_max_capacity/1.5
39
+
40
+ set :hide_in_widgets, false
41
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
42
+ end
43
+
44
+ behavior 'comment' do
45
+ set :description, "new comment"
46
+ set :selector, {
47
+ :verb => 'comment'
48
+ }
49
+ set :adjustment, {
50
+ :points => 1, :karma => 1
51
+ }
52
+
53
+ set :enable_count_limiting, false
54
+ # set :limit_per_player, 20
55
+
56
+ set :enable_rate_limiting, true
57
+ set :bucket_max_capacity, 2
58
+ # max capacity (i.e. max number of times the behavior is
59
+ # performed) per number of hours.
60
+ set :bucket_drain_rate, bucket_max_capacity/1.5
61
+
62
+ set :hide_in_widgets, false
63
+ set :icon, "http://s3.amazonaws.com/icons/icon1.png"
64
+ end
65
+
66
+
67
+ behavior 'ask' do
68
+ set :description, "ask a question"
69
+ set :selector, {
70
+ :verb => 'ask'
71
+ }
72
+
73
+ set :enable_count_limiting, false
74
+ set :enable_rate_limiting, true
75
+ set :bucket_max_capacity, 2
76
+ set :bucket_drain_rate, bucket_max_capacity/1.5
77
+
78
+ set :hide_in_widgets, false
79
+ end
80
+
81
+ # behavior 'comment_databases' do
82
+ # set :description, "new comment in category databases"
83
+ # set :selector, {
84
+ # :verb => 'comment',
85
+ # :category_slug => 'databases'
86
+ # }
87
+ # set :adjustment, {
88
+ # :points => 1, :karma => 1
89
+ # }
90
+ #
91
+ # set :enable_count_limiting, true
92
+ # set :limit_per_player, 10
93
+ # set :limit_field_scope, 'category_id'
94
+ #
95
+ # set :enable_rate_limiting, true
96
+ # set :bucket_max_capacity, 2
97
+ # set :bucket_drain_rate, bucket_max_capacity/1.5
98
+ #
99
+ # set :hide_in_widgets, false
100
+ # set :icon, "http://s3.amazonaws.com/icons/icon1.png"
101
+ # end
102
+
103
+ r_member = reward 'member' do
104
+ set :reward_template, {
105
+ :message => "Congrats, you signed in for the first time!"
106
+ }
107
+ set :components, [
108
+ {:command => "count", :comparator => 1, :where => {:verb => 'signin', :player_id => "%player_id"}}
109
+ ]
110
+ set :adjustment, {
111
+ :points => 2
112
+ }
113
+ set :active, true
114
+ set :allow_duplicates, false
115
+ end
116
+
117
+ r_active_member = reward 'active member' do
118
+ set :reward_template, {
119
+ :message => "Looks like you like the site, thank you and keep up on being active on the site!"
120
+ }
121
+ set :components, [
122
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'signin', :player_id => "%player_id"}}
123
+ ]
124
+ set :adjustment, {
125
+ :points => 5
126
+ }
127
+ set :active, true
128
+ set :allow_duplicates, false
129
+ end
130
+
131
+ r_reader = reward 'reader' do
132
+ set :reward_template, {
133
+ :message => "You've read more than 10 pages!"
134
+ }
135
+ set :components, [
136
+ {:command => "count", :comparator => {"$gt" => 10}, :where => {:verb => 'visit', :player_id => "%player_id"}}
137
+ ]
138
+ set :adjustment, {
139
+ :points => 3
140
+ }
141
+ set :active, true
142
+ set :allow_duplicates, false
143
+ end
144
+
145
+ r_commenter = reward 'commenter' do
146
+ set :reward_template, {
147
+ :message => "Congrats, you commented on something!"
148
+ }
149
+ set :components, [
150
+ {:command => "count", :comparator => 1, :where => {:verb => 'comment', :player_id => "%player_id"}}
151
+ ]
152
+ set :adjustment, {
153
+ :points => 1
154
+ }
155
+ set :active, true
156
+ set :allow_duplicates, false
157
+ end
158
+
159
+ r_active_commenter = reward 'active commenter' do
160
+ set :reward_template, {
161
+ :message => "You have commented more than 3 times in any category!"
162
+ }
163
+ set :components, [
164
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'comment', :player_id => "%player_id"}}
165
+ ]
166
+ set :adjustment, {
167
+ :points => 3
168
+ }
169
+ set :active, true
170
+ set :allow_duplicates, false
171
+ end
172
+
173
+ r_courrier_commenter = reward 'courrier commenter' do
174
+ set :reward_template, {
175
+ :message => "You have commented more than 3 times in the courrier category!"
176
+ }
177
+ set :components, [
178
+ {:command => "count", :comparator => {"$gt" => 3}, :where => {:verb => 'comment', :player_id => "%player_id", :category_slug => "courrier"}}
179
+ ]
180
+ set :adjustment, {
181
+ :points => 3
182
+ }
183
+ set :active, true
184
+ set :allow_duplicates, false
185
+ end
186
+
187
+ mission 'community member' do
188
+ # allow a player to complete this mission more than once?
189
+ set :repeatable, false
190
+ set :active, true
191
+ # give points and reward upon completing mission? (This is required for track progression)
192
+ set :enable_rewards, true
193
+ # points and secondary units to award when completing a mission
194
+ set :adjustment, {
195
+ :points => 10
196
+ }
197
+ set :reward_definition_ids do [r_active_commenter._id, r_db_commenter._id] end
198
+ end
199
+
200
+ # reward 'top commenter' do
201
+ # set :reward_template, {
202
+ # :message => "Congrats!"
203
+ # }
204
+ # set :components, [
205
+ # {:command => "count", :comparator => 1, :where => {:verb => 'comment', :player_id => "%player_id"}},
206
+ # # the first player who performs at least twice the 'new_question' behaviour
207
+ # {:command => "count", :comparator => {"$gt" => 2}, :where => {:verb => 'new_question', :site_id => "%site_id"}}
208
+ # ]
209
+ # set :adjustment, {
210
+ # :points => 5
211
+ # }
212
+ # set :active, true
213
+ # set :allow_duplicates, false
214
+ # end
215
+ end
216
+ end
217
+
218
+ network.save!
data/gamifier.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/gamifier/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Cyril Rohr"]
6
+ gem.email = ["cyril.rohr@gmail.com"]
7
+ gem.description = %q{Gem for accessing game engine APIs}
8
+ gem.summary = %q{Currently supports Badgeville Core API}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "gamifier"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Gamifier::VERSION
17
+
18
+ gem.add_dependency "faraday", "~> 0.4.1"
19
+ gem.add_dependency "json"
20
+ gem.add_dependency "rack"
21
+
22
+ gem.add_development_dependency('rspec', '~> 2')
23
+ gem.add_development_dependency('webmock')
24
+ end
@@ -0,0 +1,26 @@
1
+ require 'gamifier/model'
2
+
3
+ module Gamifier
4
+ class Collection
5
+ include Gamifier::Model::FinderMethods
6
+
7
+ attr_accessor :engine
8
+ attr_reader :model
9
+
10
+ def path
11
+ model.path
12
+ end
13
+
14
+ def initialize(engine, model)
15
+ @engine = engine
16
+ @model = model
17
+ self.extend model::FinderMethods
18
+ end
19
+
20
+ def build(entry)
21
+ instance = model.new(entry)
22
+ instance.engine = engine
23
+ instance
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require 'forwardable'
2
+
3
+ module Gamifier
4
+ module DSL
5
+ class Network
6
+ extend Forwardable
7
+ def_delegator :Gamifier, :engine, :engine
8
+
9
+ attr_reader :sites
10
+
11
+ def initialize
12
+ @sites = []
13
+ end
14
+
15
+ def site(name, &block)
16
+ new_site = DSL::Site.new(:name => name)
17
+ new_site.source.engine = engine
18
+ @sites.push(new_site)
19
+
20
+ DSL.eval_with_context(new_site, &block)
21
+ end
22
+
23
+ def save!
24
+ sites.each do |site|
25
+ if gsite = engine.sites.find(site.url)
26
+ site._id = gsite._id
27
+ end
28
+ site.save
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end