Compare View
Commits (27)
-
Add script to fix pontuation See merge request !3
-
This issue is caused by delayed_job. See more on https://softwarepublico.gov.br/gitlab/noosfero-plugins/gamification/issues/1
-
Fix pontuation check and add check for badges See merge request !5
-
Save the ids of people already checked and skip it on next load See merge request !6
Showing
37 changed files
Show diff stats
controllers/admin/gamification_plugin_badges_controller.rb
1 | class GamificationPluginBadgesController < PluginAdminController | 1 | class GamificationPluginBadgesController < PluginAdminController |
2 | 2 | ||
3 | def index | 3 | def index |
4 | - @gamification_plugin_badges = environment.gamification_plugin_badges | 4 | + @gamification_plugin_badges = environment.gamification_plugin_badges.group_by(&:owner) |
5 | end | 5 | end |
6 | 6 | ||
7 | def show | 7 | def show |
@@ -17,8 +17,13 @@ class GamificationPluginBadgesController < PluginAdminController | @@ -17,8 +17,13 @@ class GamificationPluginBadgesController < PluginAdminController | ||
17 | end | 17 | end |
18 | 18 | ||
19 | def create | 19 | def create |
20 | + owner_id = params[:gamification_plugin_badge].delete(:owner_id) | ||
20 | @gamification_plugin_badge = GamificationPlugin::Badge.new(params[:gamification_plugin_badge]) | 21 | @gamification_plugin_badge = GamificationPlugin::Badge.new(params[:gamification_plugin_badge]) |
21 | - @gamification_plugin_badge.owner = environment | 22 | + if owner_id.present? |
23 | + @gamification_plugin_badge.owner = environment.organizations.find(owner_id) | ||
24 | + else | ||
25 | + @gamification_plugin_badge.owner = environment | ||
26 | + end | ||
22 | 27 | ||
23 | if @gamification_plugin_badge.save | 28 | if @gamification_plugin_badge.save |
24 | session[:notice] = _('Badge was successfully created.') | 29 | session[:notice] = _('Badge was successfully created.') |
@@ -31,6 +36,14 @@ class GamificationPluginBadgesController < PluginAdminController | @@ -31,6 +36,14 @@ class GamificationPluginBadgesController < PluginAdminController | ||
31 | def update | 36 | def update |
32 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) | 37 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) |
33 | 38 | ||
39 | + # FIXME avoid code duplication | ||
40 | + owner_id = params[:gamification_plugin_badge].delete(:owner_id) | ||
41 | + if owner_id.present? | ||
42 | + @gamification_plugin_badge.owner = environment.organizations.find(owner_id) | ||
43 | + else | ||
44 | + @gamification_plugin_badge.owner = environment | ||
45 | + end | ||
46 | + | ||
34 | if @gamification_plugin_badge.update_attributes(params[:gamification_plugin_badge]) | 47 | if @gamification_plugin_badge.update_attributes(params[:gamification_plugin_badge]) |
35 | session[:notice] = _('Badge was successfully updated.') | 48 | session[:notice] = _('Badge was successfully updated.') |
36 | redirect_to :action => :index | 49 | redirect_to :action => :index |
@@ -39,6 +52,10 @@ class GamificationPluginBadgesController < PluginAdminController | @@ -39,6 +52,10 @@ class GamificationPluginBadgesController < PluginAdminController | ||
39 | end | 52 | end |
40 | end | 53 | end |
41 | 54 | ||
55 | + def search_owners | ||
56 | + render :text => prepare_to_token_input(environment.organizations).to_json | ||
57 | + end | ||
58 | + | ||
42 | def destroy | 59 | def destroy |
43 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) | 60 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) |
44 | @gamification_plugin_badge.destroy | 61 | @gamification_plugin_badge.destroy |
lib/ext/environment.rb
@@ -2,6 +2,11 @@ require_dependency 'environment' | @@ -2,6 +2,11 @@ require_dependency 'environment' | ||
2 | 2 | ||
3 | class Environment | 3 | class Environment |
4 | 4 | ||
5 | - has_many :gamification_plugin_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner | 5 | + has_many :gamification_plugin_environment_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner |
6 | + has_many :gamification_plugin_organization_badges, :through => :organizations | ||
7 | + | ||
8 | + def gamification_plugin_badges | ||
9 | + GamificationPlugin::Badge.joins('left join profiles on profiles.id = owner_id').where(['owner_id = ? or profiles.environment_id = ?', self.id, self.id]) | ||
10 | + end | ||
6 | 11 | ||
7 | end | 12 | end |
lib/gamification_plugin/api.rb
@@ -3,7 +3,7 @@ class GamificationPlugin::API < Grape::API | @@ -3,7 +3,7 @@ class GamificationPlugin::API < Grape::API | ||
3 | resource :gamification_plugin do | 3 | resource :gamification_plugin do |
4 | 4 | ||
5 | get 'badges' do | 5 | get 'badges' do |
6 | - environment.gamification_plugin_badges.group(:name).count | 6 | + environment.gamification_plugin_badges.group('gamification_plugin_badges.name').count |
7 | end | 7 | end |
8 | 8 | ||
9 | resource :my do | 9 | resource :my do |
@@ -57,7 +57,7 @@ class GamificationPlugin::API < Grape::API | @@ -57,7 +57,7 @@ class GamificationPlugin::API < Grape::API | ||
57 | get ':id/points_by_profile' do | 57 | get ':id/points_by_profile' do |
58 | person = environment.people.visible_for_person(current_person).find_by_id(params[:id]) | 58 | person = environment.people.visible_for_person(current_person).find_by_id(params[:id]) |
59 | return not_found! if person.blank? | 59 | return not_found! if person.blank? |
60 | - {points: person.points_by_type(params[:profile]) } | 60 | + {points: person.points_by_profile(params[:profile]) } |
61 | end | 61 | end |
62 | 62 | ||
63 | get ':id/points_out_of_profiles' do | 63 | get ':id/points_out_of_profiles' do |
@@ -75,4 +75,3 @@ class GamificationPlugin::API < Grape::API | @@ -75,4 +75,3 @@ class GamificationPlugin::API < Grape::API | ||
75 | end | 75 | end |
76 | end | 76 | end |
77 | end | 77 | end |
78 | - |
lib/gamification_plugin/badge.rb
lib/gamification_plugin/dashboard_helper.rb
@@ -12,13 +12,22 @@ module GamificationPlugin::DashboardHelper | @@ -12,13 +12,22 @@ module GamificationPlugin::DashboardHelper | ||
12 | end | 12 | end |
13 | 13 | ||
14 | def score_point_category(point) | 14 | def score_point_category(point) |
15 | - point = GamificationPlugin::PointsType.where(name: point.score.category).first | 15 | + point = GamificationPlugin::PointsType.where(id: point.score.category).first |
16 | point.nil? ? '' : point.description | 16 | point.nil? ? '' : point.description |
17 | end | 17 | end |
18 | 18 | ||
19 | + def score_point_target_link(point, text) | ||
20 | + url = Merit::PointRules.target_url(point) | ||
21 | + url.present? ? link_to(text, url) : text | ||
22 | + end | ||
23 | + | ||
24 | + def score_point_action_class(point) | ||
25 | + point.undo_rule? ? 'undo_action':'do_action' | ||
26 | + end | ||
27 | + | ||
19 | def ranking(target, from_date=nil, limit=10) | 28 | def ranking(target, from_date=nil, limit=10) |
20 | # FIXME move these queries to profile model | 29 | # FIXME move these queries to profile model |
21 | - ranking = Profile.select('profiles.*, sum(num_points) as gamification_points, ROW_NUMBER() OVER(order by sum(num_points) DESC) as gamification_position').joins(:sash => {:scores => :score_points}).where(:type => target.class).order('sum(num_points) DESC').group('profiles.id') | 30 | + ranking = Profile.select('profiles.*, sum(num_points) as gamification_points, ROW_NUMBER() OVER(order by sum(num_points) DESC) as gamification_position').joins(:sash => {:scores => :score_points}).where(:type => target.class).reorder('sum(num_points) DESC').group('profiles.id') |
22 | ranking = ranking.where("merit_score_points.created_at >= ?", from_date) if from_date.present? | 31 | ranking = ranking.where("merit_score_points.created_at >= ?", from_date) if from_date.present? |
23 | target_ranking = Profile.from("(#{ranking.to_sql}) profiles").where('profiles.id' => target.id).first | 32 | target_ranking = Profile.from("(#{ranking.to_sql}) profiles").where('profiles.id' => target.id).first |
24 | 33 | ||
@@ -35,4 +44,15 @@ module GamificationPlugin::DashboardHelper | @@ -35,4 +44,15 @@ module GamificationPlugin::DashboardHelper | ||
35 | (context_ranking.blank? ? '' : render(:partial => 'gamification/ranking', :locals => {:ranking => context_ranking, :target_ranking => target_ranking, :ranking_class => 'context'})) | 44 | (context_ranking.blank? ? '' : render(:partial => 'gamification/ranking', :locals => {:ranking => context_ranking, :target_ranking => target_ranking, :ranking_class => 'context'})) |
36 | end | 45 | end |
37 | 46 | ||
47 | + def badges_title(owner) | ||
48 | + return _('Badges for %s' % owner.name) if owner.kind_of?(Organization) | ||
49 | + _('Badges') | ||
50 | + end | ||
51 | + | ||
52 | + def grouped_badges | ||
53 | + environment.gamification_plugin_badges.all.group_by(&:owner).sort do |a, b| | ||
54 | + a.first.kind_of?(Environment) ? -1 : a.first.name <=> b.first.name | ||
55 | + end | ||
56 | + end | ||
57 | + | ||
38 | end | 58 | end |
lib/merit/badge_rules.rb
@@ -14,6 +14,7 @@ module Merit | @@ -14,6 +14,7 @@ module Merit | ||
14 | action: 'comment#create', | 14 | action: 'comment#create', |
15 | default_threshold: 5, | 15 | default_threshold: 5, |
16 | to: :author, | 16 | to: :author, |
17 | + target_profile: lambda {|comment| comment.profile }, | ||
17 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } | 18 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
18 | } | 19 | } |
19 | ], | 20 | ], |
@@ -22,6 +23,7 @@ module Merit | @@ -22,6 +23,7 @@ module Merit | ||
22 | action: 'comment#create', | 23 | action: 'comment#create', |
23 | default_threshold: 5, | 24 | default_threshold: 5, |
24 | to: lambda {|comment| comment.source.author}, | 25 | to: lambda {|comment| comment.source.author}, |
26 | + target_profile: lambda {|comment| comment.profile }, | ||
25 | value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.where(author_id: author.id)).count : 0 } | 27 | value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.where(author_id: author.id)).count : 0 } |
26 | } | 28 | } |
27 | ], | 29 | ], |
@@ -30,6 +32,7 @@ module Merit | @@ -30,6 +32,7 @@ module Merit | ||
30 | action: 'article#create', | 32 | action: 'article#create', |
31 | default_threshold: 5, | 33 | default_threshold: 5, |
32 | to: :author, | 34 | to: :author, |
35 | + target_profile: lambda {|article| article.profile }, | ||
33 | value: lambda { |article, author| author.present? ? TextArticle.where(author_id: author.id).count : 0 } | 36 | value: lambda { |article, author| author.present? ? TextArticle.where(author_id: author.id).count : 0 } |
34 | }, | 37 | }, |
35 | ], | 38 | ], |
@@ -38,6 +41,7 @@ module Merit | @@ -38,6 +41,7 @@ module Merit | ||
38 | action: 'vote#create', | 41 | action: 'vote#create', |
39 | default_threshold: 5, | 42 | default_threshold: 5, |
40 | to: lambda {|vote| vote.voteable.author}, | 43 | to: lambda {|vote| vote.voteable.author}, |
44 | + target_profile: lambda {|vote| vote.voteable.profile }, | ||
41 | value: lambda { |vote, author| vote.voteable ? Vote.for_voteable(vote.voteable).where('vote > 0').count : 0} | 45 | value: lambda { |vote, author| vote.voteable ? Vote.for_voteable(vote.voteable).where('vote > 0').count : 0} |
42 | } | 46 | } |
43 | ], | 47 | ], |
@@ -46,6 +50,7 @@ module Merit | @@ -46,6 +50,7 @@ module Merit | ||
46 | action: 'vote#create', | 50 | action: 'vote#create', |
47 | default_threshold: 5, | 51 | default_threshold: 5, |
48 | to: lambda {|vote| vote.voteable.author}, | 52 | to: lambda {|vote| vote.voteable.author}, |
53 | + target_profile: lambda {|vote| vote.voteable.profile }, | ||
49 | value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count } | 54 | value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count } |
50 | } | 55 | } |
51 | ], | 56 | ], |
@@ -54,6 +59,7 @@ module Merit | @@ -54,6 +59,7 @@ module Merit | ||
54 | action: 'vote#create', | 59 | action: 'vote#create', |
55 | default_threshold: 5, | 60 | default_threshold: 5, |
56 | to: lambda {|vote| vote.voter}, | 61 | to: lambda {|vote| vote.voter}, |
62 | + target_profile: lambda {|vote| vote.voteable.profile }, | ||
57 | value: lambda { |vote, voter| voter ? Vote.for_voter(voter).count : 0 } | 63 | value: lambda { |vote, voter| voter ? Vote.for_voter(voter).count : 0 } |
58 | } | 64 | } |
59 | ], | 65 | ], |
@@ -65,6 +71,7 @@ module Merit | @@ -65,6 +71,7 @@ module Merit | ||
65 | value: lambda { |friendship, person| person.friends.count } | 71 | value: lambda { |friendship, person| person.friends.count } |
66 | } | 72 | } |
67 | ], | 73 | ], |
74 | + manual: [], | ||
68 | 75 | ||
69 | #FIXME review the name of the badges and see a way to make it generic | 76 | #FIXME review the name of the badges and see a way to make it generic |
70 | creative: [ | 77 | creative: [ |
@@ -72,12 +79,14 @@ module Merit | @@ -72,12 +79,14 @@ module Merit | ||
72 | action: 'comment#create', | 79 | action: 'comment#create', |
73 | default_threshold: 5, | 80 | default_threshold: 5, |
74 | to: :author, | 81 | to: :author, |
82 | + target_profile: lambda {|comment| comment.profile }, | ||
75 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } | 83 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
76 | }, | 84 | }, |
77 | { | 85 | { |
78 | action: 'article#create', | 86 | action: 'article#create', |
79 | default_threshold: 5, | 87 | default_threshold: 5, |
80 | to: :author, | 88 | to: :author, |
89 | + target_profile: lambda {|article| article.profile }, | ||
81 | value: lambda { |article, author| author.present? ? author.articles.count : 0 } | 90 | value: lambda { |article, author| author.present? ? author.articles.count : 0 } |
82 | }, | 91 | }, |
83 | ], | 92 | ], |
@@ -86,6 +95,7 @@ module Merit | @@ -86,6 +95,7 @@ module Merit | ||
86 | action: 'articlefollower#create', | 95 | action: 'articlefollower#create', |
87 | default_threshold: 5, | 96 | default_threshold: 5, |
88 | to: lambda {|article| article.person }, | 97 | to: lambda {|article| article.person }, |
98 | + target_profile: lambda {|article_follower| article_follower.article.profile }, | ||
89 | model: 'ArticleFollower', | 99 | model: 'ArticleFollower', |
90 | value: lambda { |article, person| person.present? ? person.article_followers.count : 0 } | 100 | value: lambda { |article, person| person.present? ? person.article_followers.count : 0 } |
91 | } | 101 | } |
@@ -95,12 +105,14 @@ module Merit | @@ -95,12 +105,14 @@ module Merit | ||
95 | action: 'Vote#create', | 105 | action: 'Vote#create', |
96 | default_threshold: 5, | 106 | default_threshold: 5, |
97 | to: lambda { |vote| vote.voter }, | 107 | to: lambda { |vote| vote.voter }, |
108 | + target_profile: lambda {|vote| vote.voteable.profile }, | ||
98 | value: lambda { |vote, voter| Vote.for_voter(voter).count } | 109 | value: lambda { |vote, voter| Vote.for_voter(voter).count } |
99 | }, | 110 | }, |
100 | { | 111 | { |
101 | action: 'Event#create', | 112 | action: 'Event#create', |
102 | default_threshold: 5, | 113 | default_threshold: 5, |
103 | to: lambda { |article| article.author }, | 114 | to: lambda { |article| article.author }, |
115 | + target_profile: lambda {|article| article.profile }, | ||
104 | value: lambda { |event, author| author.events.count } | 116 | value: lambda { |event, author| author.events.count } |
105 | }, | 117 | }, |
106 | ], | 118 | ], |
@@ -109,12 +121,14 @@ module Merit | @@ -109,12 +121,14 @@ module Merit | ||
109 | action: 'vote#create', | 121 | action: 'vote#create', |
110 | default_threshold: 5, | 122 | default_threshold: 5, |
111 | to: lambda {|vote| vote.voter}, | 123 | to: lambda {|vote| vote.voter}, |
124 | + target_profile: lambda {|vote| vote.voteable.profile }, | ||
112 | value: lambda { |vote, voter| voter ? voter.votes.where('vote > 0').count : 0 } | 125 | value: lambda { |vote, voter| voter ? voter.votes.where('vote > 0').count : 0 } |
113 | }, | 126 | }, |
114 | { | 127 | { |
115 | action: 'comment#create', | 128 | action: 'comment#create', |
116 | default_threshold: 5, | 129 | default_threshold: 5, |
117 | to: :author, | 130 | to: :author, |
131 | + target_profile: lambda {|comment| comment.profile }, | ||
118 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } | 132 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
119 | } | 133 | } |
120 | ], | 134 | ], |
@@ -123,6 +137,7 @@ module Merit | @@ -123,6 +137,7 @@ module Merit | ||
123 | action: 'articlefollower#create', | 137 | action: 'articlefollower#create', |
124 | default_threshold: 5, | 138 | default_threshold: 5, |
125 | to: :person, | 139 | to: :person, |
140 | + target_profile: lambda {|article_follower| article_follower.article.profile }, | ||
126 | model: 'ArticleFollower', | 141 | model: 'ArticleFollower', |
127 | value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 } | 142 | value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 } |
128 | }, | 143 | }, |
@@ -130,11 +145,28 @@ module Merit | @@ -130,11 +145,28 @@ module Merit | ||
130 | action: 'comment#create', | 145 | action: 'comment#create', |
131 | default_threshold: 5, | 146 | default_threshold: 5, |
132 | to: :author, | 147 | to: :author, |
148 | + target_profile: lambda {|comment| comment.profile }, | ||
133 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } | 149 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
134 | }, | 150 | }, |
135 | ] | 151 | ] |
136 | } | 152 | } |
137 | 153 | ||
154 | + def target_author(source, setting) | ||
155 | + if setting[:to].is_a? Symbol | ||
156 | + source.send(setting[:to]) | ||
157 | + else | ||
158 | + setting[:to].call(source) rescue nil | ||
159 | + end | ||
160 | + end | ||
161 | + | ||
162 | + def target_profile(source, setting) | ||
163 | + setting[:target_profile].present? ? setting[:target_profile].call(source) : nil | ||
164 | + end | ||
165 | + | ||
166 | + def check_organization_badge(badge, source, setting) | ||
167 | + !badge.owner.kind_of?(Organization) || badge.owner == target_profile(source, setting) | ||
168 | + end | ||
169 | + | ||
138 | def initialize(environment=nil) | 170 | def initialize(environment=nil) |
139 | return if environment.nil? | 171 | return if environment.nil? |
140 | @environment = environment | 172 | @environment = environment |
@@ -142,7 +174,7 @@ module Merit | @@ -142,7 +174,7 @@ module Merit | ||
142 | rules = AVAILABLE_RULES | 174 | rules = AVAILABLE_RULES |
143 | rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES | 175 | rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES |
144 | 176 | ||
145 | - environment.gamification_plugin_badges.all.each do |badge| | 177 | + environment.gamification_plugin_badges.each do |badge| |
146 | next if rules[badge.name.to_sym].nil? | 178 | next if rules[badge.name.to_sym].nil? |
147 | rules[badge.name.to_sym].each do |setting| | 179 | rules[badge.name.to_sym].each do |setting| |
148 | options = {badge: badge.name, level: badge.level, to: setting[:to]} | 180 | options = {badge: badge.name, level: badge.level, to: setting[:to]} |
@@ -150,18 +182,11 @@ module Merit | @@ -150,18 +182,11 @@ module Merit | ||
150 | grant_on setting[:action], options do |source| | 182 | grant_on setting[:action], options do |source| |
151 | can_be_granted = true | 183 | can_be_granted = true |
152 | rules[badge.name.to_sym].each do |s| | 184 | rules[badge.name.to_sym].each do |s| |
153 | - if setting[:to].is_a? Symbol | ||
154 | - to = source.send(setting[:to]) | ||
155 | - else | ||
156 | - begin | ||
157 | - to = setting[:to].call(source) | ||
158 | - rescue | ||
159 | - to = nil | ||
160 | - end | ||
161 | - end | ||
162 | - # pass source and to for different situations | 185 | + to = target_author(source, setting) |
186 | + # pass source and to for different situations | ||
163 | action = (badge.custom_fields || {}).fetch(s[:action], {}) | 187 | action = (badge.custom_fields || {}).fetch(s[:action], {}) |
164 | can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i | 188 | can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i |
189 | + can_be_granted &= check_organization_badge(badge, source, setting) | ||
165 | end | 190 | end |
166 | can_be_granted | 191 | can_be_granted |
167 | end | 192 | end |
lib/merit/point_rules.rb
@@ -11,6 +11,7 @@ module Merit | @@ -11,6 +11,7 @@ module Merit | ||
11 | description: _('Comment author'), | 11 | description: _('Comment author'), |
12 | default_weight: 40, | 12 | default_weight: 40, |
13 | target_profile: lambda {|comment| comment.source.profile }, | 13 | target_profile: lambda {|comment| comment.source.profile }, |
14 | + target_url: lambda {|comment| comment.url}, | ||
14 | }, | 15 | }, |
15 | comment_article_author: { | 16 | comment_article_author: { |
16 | action: 'comment#create', | 17 | action: 'comment#create', |
@@ -20,6 +21,7 @@ module Merit | @@ -20,6 +21,7 @@ module Merit | ||
20 | description: _('Article author of a comment'), | 21 | description: _('Article author of a comment'), |
21 | default_weight: 50, | 22 | default_weight: 50, |
22 | target_profile: lambda {|comment| comment.source.profile }, | 23 | target_profile: lambda {|comment| comment.source.profile }, |
24 | + target_url: lambda {|comment| comment.url}, | ||
23 | }, | 25 | }, |
24 | comment_article: { | 26 | comment_article: { |
25 | action: 'comment#create', | 27 | action: 'comment#create', |
@@ -29,6 +31,7 @@ module Merit | @@ -29,6 +31,7 @@ module Merit | ||
29 | description: _('Source article of a comment'), | 31 | description: _('Source article of a comment'), |
30 | default_weight: 50, | 32 | default_weight: 50, |
31 | target_profile: lambda {|comment| comment.source.profile }, | 33 | target_profile: lambda {|comment| comment.source.profile }, |
34 | + target_url: lambda {|comment| comment.url}, | ||
32 | }, | 35 | }, |
33 | comment_community: { | 36 | comment_community: { |
34 | action: 'comment#create', | 37 | action: 'comment#create', |
@@ -38,7 +41,8 @@ module Merit | @@ -38,7 +41,8 @@ module Merit | ||
38 | description: _('Article community of a comment'), | 41 | description: _('Article community of a comment'), |
39 | default_weight: 50, | 42 | default_weight: 50, |
40 | target_profile: lambda {|comment| comment.source.profile }, | 43 | target_profile: lambda {|comment| comment.source.profile }, |
41 | - condition: lambda {|comment, profile| comment.profile.community?} | 44 | + condition: lambda {|comment, profile| comment.profile.community?}, |
45 | + target_url: lambda {|comment| comment.url}, | ||
42 | }, | 46 | }, |
43 | article_author: { | 47 | article_author: { |
44 | action: 'article#create', | 48 | action: 'article#create', |
@@ -48,6 +52,7 @@ module Merit | @@ -48,6 +52,7 @@ module Merit | ||
48 | description: _('Article author'), | 52 | description: _('Article author'), |
49 | default_weight: 50, | 53 | default_weight: 50, |
50 | target_profile: lambda {|article| article.profile }, | 54 | target_profile: lambda {|article| article.profile }, |
55 | + target_url: lambda {|article| article.url}, | ||
51 | }, | 56 | }, |
52 | article_community: { | 57 | article_community: { |
53 | action: 'article#create', | 58 | action: 'article#create', |
@@ -57,7 +62,8 @@ module Merit | @@ -57,7 +62,8 @@ module Merit | ||
57 | description: _('Article community'), | 62 | description: _('Article community'), |
58 | default_weight: 10, | 63 | default_weight: 10, |
59 | target_profile: lambda {|article| article.profile }, | 64 | target_profile: lambda {|article| article.profile }, |
60 | - condition: lambda {|article, profile| article.profile.present? and article.profile.community? } | 65 | + condition: lambda {|article, profile| article.profile.present? and article.profile.community? }, |
66 | + target_url: lambda {|article| article.url}, | ||
61 | }, | 67 | }, |
62 | vote_voteable_author: { | 68 | vote_voteable_author: { |
63 | action: 'vote#create', | 69 | action: 'vote#create', |
@@ -67,6 +73,7 @@ module Merit | @@ -67,6 +73,7 @@ module Merit | ||
67 | description: _('Author of a voted content'), | 73 | description: _('Author of a voted content'), |
68 | default_weight: 20, | 74 | default_weight: 20, |
69 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, | 75 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
76 | + target_url: lambda {|vote| vote.voteable.url}, | ||
70 | }, | 77 | }, |
71 | vote_voteable: { | 78 | vote_voteable: { |
72 | action: 'vote#create', | 79 | action: 'vote#create', |
@@ -76,6 +83,7 @@ module Merit | @@ -76,6 +83,7 @@ module Merit | ||
76 | description: _('Voted content'), | 83 | description: _('Voted content'), |
77 | default_weight: 30, | 84 | default_weight: 30, |
78 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, | 85 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
86 | + target_url: lambda {|vote| vote.voteable.url}, | ||
79 | }, | 87 | }, |
80 | vote_voter: { | 88 | vote_voter: { |
81 | action: 'vote#create', | 89 | action: 'vote#create', |
@@ -85,6 +93,7 @@ module Merit | @@ -85,6 +93,7 @@ module Merit | ||
85 | description: _('Voter'), | 93 | description: _('Voter'), |
86 | default_weight: 10, | 94 | default_weight: 10, |
87 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, | 95 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
96 | + target_url: lambda {|vote| vote.voteable.url}, | ||
88 | }, | 97 | }, |
89 | friends: { | 98 | friends: { |
90 | action: 'friendship#create', | 99 | action: 'friendship#create', |
@@ -150,6 +159,7 @@ module Merit | @@ -150,6 +159,7 @@ module Merit | ||
150 | end | 159 | end |
151 | 160 | ||
152 | def profile_condition(setting, target, profile) | 161 | def profile_condition(setting, target, profile) |
162 | + return false if target == true | ||
153 | profile.nil? || setting[:target_profile].blank? || setting[:target_profile].call(target) == profile | 163 | profile.nil? || setting[:target_profile].blank? || setting[:target_profile].call(target) == profile |
154 | end | 164 | end |
155 | 165 | ||
@@ -163,6 +173,15 @@ module Merit | @@ -163,6 +173,15 @@ module Merit | ||
163 | end | 173 | end |
164 | end | 174 | end |
165 | 175 | ||
176 | + def self.target_url(point) | ||
177 | + rule_name = point.point_type.present? ? point.point_type.name : point.score.category | ||
178 | + target_url = AVAILABLE_RULES[rule_name.to_sym][:target_url] | ||
179 | + return nil if target_url.blank? || point.action.blank? | ||
180 | + | ||
181 | + model = BaseTargetFinder.new(Merit::Rule.new, point.action).get_target_from_database | ||
182 | + model.present? ? target_url.call(model) : nil | ||
183 | + end | ||
184 | + | ||
166 | def initialize(environment=nil) | 185 | def initialize(environment=nil) |
167 | return if environment.nil? | 186 | return if environment.nil? |
168 | @environment = environment | 187 | @environment = environment |
lib/merit_ext.rb
@@ -17,6 +17,15 @@ module Merit | @@ -17,6 +17,15 @@ module Merit | ||
17 | class Score | 17 | class Score |
18 | class Point | 18 | class Point |
19 | belongs_to :action | 19 | belongs_to :action |
20 | + | ||
21 | + def point_type | ||
22 | + @point_type ||= GamificationPlugin::PointsType.where(id: score.category).first | ||
23 | + end | ||
24 | + | ||
25 | + def undo_rule? | ||
26 | + rule = Merit::PointRules::AVAILABLE_RULES[point_type.name.to_sym] | ||
27 | + rule[:undo_action] == "#{action.target_model}##{action.action_method}" | ||
28 | + end | ||
20 | end | 29 | end |
21 | end | 30 | end |
22 | 31 | ||
@@ -34,7 +43,7 @@ module Merit | @@ -34,7 +43,7 @@ module Merit | ||
34 | module ClassMethods | 43 | module ClassMethods |
35 | 44 | ||
36 | def has_merit_actions(options = {}) | 45 | def has_merit_actions(options = {}) |
37 | - after_create { |obj| obj.new_merit_action(:create, options) } | 46 | + after_create { |obj| obj.delay.new_merit_action(:create, options) } |
38 | before_destroy { |obj| obj.new_merit_action(:destroy, options) } | 47 | before_destroy { |obj| obj.new_merit_action(:destroy, options) } |
39 | end | 48 | end |
40 | 49 |
models/gamification_plugin/points_categorization.rb
1 | -class GamificationPlugin::PointsCategorization < Noosfero::Plugin::ActiveRecord | 1 | +class GamificationPlugin::PointsCategorization < ActiveRecord::Base |
2 | belongs_to :profile | 2 | belongs_to :profile |
3 | belongs_to :point_type, class_name: 'GamificationPlugin::PointsType', foreign_key: :point_type_id | 3 | belongs_to :point_type, class_name: 'GamificationPlugin::PointsType', foreign_key: :point_type_id |
4 | attr_accessible :profile_id, :profile, :point_type_id, :weight | 4 | attr_accessible :profile_id, :profile, :point_type_id, :weight |
@@ -10,5 +10,5 @@ class GamificationPlugin::PointsCategorization < Noosfero::Plugin::ActiveRecord | @@ -10,5 +10,5 @@ class GamificationPlugin::PointsCategorization < Noosfero::Plugin::ActiveRecord | ||
10 | scope :for_type, lambda { |p_type| joins(:point_type).where(gamification_plugin_points_types: {name: p_type}) } | 10 | scope :for_type, lambda { |p_type| joins(:point_type).where(gamification_plugin_points_types: {name: p_type}) } |
11 | scope :for_profile, lambda { |p_profile| joins(:profile).where(profiles: {identifier: p_profile}) } | 11 | scope :for_profile, lambda { |p_profile| joins(:profile).where(profiles: {identifier: p_profile}) } |
12 | 12 | ||
13 | - scope :grouped_profiles, select(:profile_id).group(:profile_id).includes(:profile) | 13 | + scope :grouped_profiles, -> { select(:profile_id).group(:profile_id).includes(:profile) } |
14 | end | 14 | end |
models/gamification_plugin/points_type.rb
1 | -class GamificationPlugin::PointsType < Noosfero::Plugin::ActiveRecord | 1 | +class GamificationPlugin::PointsType < ActiveRecord::Base |
2 | attr_accessible :description, :name | 2 | attr_accessible :description, :name |
3 | 3 | ||
4 | validates :name, presence: true, uniqueness: true | 4 | validates :name, presence: true, uniqueness: true |
public/admin.css
public/admin.js
@@ -13,6 +13,11 @@ var gamificationPluginAdmin = { | @@ -13,6 +13,11 @@ var gamificationPluginAdmin = { | ||
13 | var name = jQuery('#gamification-plugin-form-badge-name').find('option:selected').text(); | 13 | var name = jQuery('#gamification-plugin-form-badge-name').find('option:selected').text(); |
14 | jQuery('.name_'+name).show(); | 14 | jQuery('.name_'+name).show(); |
15 | jQuery('.name_'+name).find('input').removeAttr('disabled'); | 15 | jQuery('.name_'+name).find('input').removeAttr('disabled'); |
16 | + if(jQuery('.name_'+name).children().length>0) { | ||
17 | + jQuery('.action-fields').show(); | ||
18 | + } else { | ||
19 | + jQuery('.action-fields').hide(); | ||
20 | + } | ||
16 | } | 21 | } |
17 | 22 | ||
18 | } | 23 | } |
public/style.css
@@ -0,0 +1,197 @@ | @@ -0,0 +1,197 @@ | ||
1 | +#!/usr/bin/env ruby | ||
2 | +# encoding: UTF-8 | ||
3 | + | ||
4 | +# | ||
5 | +# This script was created for ensuring all the actions observed | ||
6 | +# by merit for pontuation was judged and pontuated accordingly | ||
7 | +# It checks the merit_actions registers for each action(model | ||
8 | +# create or destroy) and recreates it | ||
9 | +# | ||
10 | + | ||
11 | +require 'csv' | ||
12 | + | ||
13 | +ActiveRecord::Base.logger.level = Logger::Severity::UNKNOWN | ||
14 | + | ||
15 | +class ProcessObserver | ||
16 | + def update(changed_data) | ||
17 | + merit = changed_data[:merit_object] | ||
18 | + if merit.kind_of?(Merit::Score::Point) | ||
19 | + action = Merit::Action.find(changed_data[:merit_action_id]) | ||
20 | + new_date = YAML.load(action.target_data).created_at | ||
21 | + action.update_attribute(:created_at, new_date) | ||
22 | + merit.update_attribute(:created_at, new_date) | ||
23 | + end | ||
24 | + end | ||
25 | +end | ||
26 | + | ||
27 | +def create_action(obj, index, count) | ||
28 | + target_model = obj.class.base_class.name.downcase | ||
29 | + action = Merit::Action.find_by_target_id_and_target_model_and_action_method(obj.id, target_model, 'create') | ||
30 | + if action.nil? | ||
31 | + puts "#{index}/#{count} Create merit action for #{target_model} #{obj.id}" | ||
32 | + begin | ||
33 | + obj.new_merit_action(:create) | ||
34 | + rescue Exception => e | ||
35 | + puts "Could not be create: #{e.message}" | ||
36 | + end | ||
37 | + end | ||
38 | +end | ||
39 | + | ||
40 | +def recreate_actions person, objects, category | ||
41 | + puts "Recreating actions for #{person.identifier} on model #{objects.name}" | ||
42 | + actions = Merit::Action.where(target_id: objects, target_model: objects.name.downcase, action_method: 'create') | ||
43 | + Merit::Score::Point.where(action_id: actions).destroy_all | ||
44 | + actions.destroy_all | ||
45 | + # erase remaining points if any (can be wrong on destroy cases ?) | ||
46 | + person.score_points.where(score_id: Merit::Score.where(category: category)).destroy_all | ||
47 | + count = objects.count | ||
48 | + objects.each_with_index{ |obj, index| create_action(obj, index, count) } | ||
49 | +end | ||
50 | + | ||
51 | +def calc_points categorization, objects | ||
52 | + rule = Merit::PointRules::AVAILABLE_RULES[categorization.point_type.name.to_sym] | ||
53 | + return 0 if rule.nil? | ||
54 | + | ||
55 | + sum = objects.map{|o| rule[:value].respond_to?(:call) ? rule[:value].call(o) : rule[:value] }.sum | ||
56 | + return sum * categorization.weight | ||
57 | +end | ||
58 | + | ||
59 | +# avoid updating level on every action for increasing performance | ||
60 | +Merit.observers.delete('RankObserver') | ||
61 | + | ||
62 | +Merit.observers << 'ProcessObserver' | ||
63 | + | ||
64 | +class Article < ActiveRecord::Base | ||
65 | + def self.text_article_types | ||
66 | + ['ProposalsDiscussionPlugin::Proposal'] | ||
67 | + end | ||
68 | +end | ||
69 | + | ||
70 | +puts "Cleaning up points from actions which don't exist" | ||
71 | +Merit::Score::Point.includes(:action).find_each(batch_size: 100) do |point| | ||
72 | + point.destroy if point.action.nil? | ||
73 | +end | ||
74 | + | ||
75 | +# erase the badges spreadsheet | ||
76 | +CSV.open( "gamification_wrong_badges.csv", 'w' ) do |csv| | ||
77 | + csv << ['identifier', 'missing badges', 'exceeding badges'] | ||
78 | +end | ||
79 | +# erase the points spreadsheet | ||
80 | +CSV.open( "gamification_points_out_expectation.csv", 'w' ) do |csv| | ||
81 | + csv << ['identifier', 'name', 'action', 'profile', 'category id', 'category type', 'should have', 'have'] | ||
82 | +end | ||
83 | + | ||
84 | +Environment.all.each do |environment| | ||
85 | + puts "Process environment #{environment.name}" | ||
86 | + | ||
87 | + Merit::AppPointRules.clear | ||
88 | + Merit::AppBadgeRules.clear | ||
89 | + Merit::AppPointRules.merge!(Merit::PointRules.new(environment).defined_rules) | ||
90 | + Merit::AppBadgeRules.merge!(Merit::BadgeRules.new(environment).defined_rules) | ||
91 | + | ||
92 | + group_control = YAML.load(File.read(File.join(Rails.root,'tmp','control_group.yml'))) if File.exist?(File.join(Rails.root,'tmp','control_group.yml')) | ||
93 | + conditions = group_control.nil? ? {} : {:identifier => group_control.map{|k,v| v['profiles']}.flatten} | ||
94 | + | ||
95 | + clean_profiles_file = File.join(Rails.root,'tmp','gamification_clean_profiles.yml') | ||
96 | + clean_profiles = YAML.load(File.read(clean_profiles_file)) if File.exist?(File.join(clean_profiles_file)) | ||
97 | + clean_profiles = [0] if clean_profiles.nil? | ||
98 | + | ||
99 | + people_count = environment.people.where(conditions).where("id not in (?)",clean_profiles).count | ||
100 | + person_index = 0 | ||
101 | + puts "Analising environment people" | ||
102 | + environment.people.where("id not in (?)",clean_profiles).find_each(:conditions => conditions) do |person| | ||
103 | + person_index += 1 | ||
104 | + profile_ids = GamificationPlugin::PointsCategorization.uniq.pluck(:profile_id) | ||
105 | + profile_ids.keep_if { |item| group_control.keys.include?(item) } unless group_control.nil? | ||
106 | + profile_ids.delete nil # avoid loosing time with generic for now | ||
107 | + profile_ids.each do |profile_id| | ||
108 | + profile = Profile.where(id: profile_id).first | ||
109 | + if profile.nil? | ||
110 | + profile_name = 'generic' | ||
111 | + # person actions | ||
112 | + person_articles = Article.where(author_id: person.id) | ||
113 | + comments = Comment.where(author_id: person.id) | ||
114 | + votes = Vote.for_voter(person) | ||
115 | + follows = ArticleFollower.where(person_id: person.id) | ||
116 | + else | ||
117 | + profile_name = profile.identifier | ||
118 | + #person actions | ||
119 | + person_articles = Article.where(author_id: person.id, profile_id: profile) | ||
120 | + comments = Comment.where(author_id: person.id, source_id: profile.articles) | ||
121 | + general_votes = Vote.for_voter(person) | ||
122 | + votes = general_votes.where("(voteable_type = 'Article' and voteable_id in (?)) or (voteable_type = 'Comment' and voteable_id in (?))",profile.articles, Comment.where(source_type: "Article", source_id: profile.articles)) | ||
123 | + follows = ArticleFollower.where(person_id: person.id, article_id: profile.articles) | ||
124 | + end | ||
125 | + # received actions | ||
126 | + comments_received = Comment.where(:source_id => person_articles) | ||
127 | + votes_received = Vote.where("(voteable_type = 'Article' and voteable_id in (?)) or (voteable_type = 'Comment' and voteable_id in (?))",person_articles, person.comments) | ||
128 | + follows_received = ArticleFollower.where(:article_id => person_articles) | ||
129 | + | ||
130 | + puts "#{person_index}/#{people_count} - Analising points for #{person.identifier} on #{profile_name}" | ||
131 | + #puts "Proposed #{person_articles.count} times, Commented #{comments.count} times, Voted #{votes.count} times, Followed #{follows.count} times" | ||
132 | + #puts "Received #{votes_received.count} votes, #{comments_received.count} comments, #{follows_received.count} follows\n" | ||
133 | + | ||
134 | + scope_by_badge_action = { | ||
135 | + "articlefollower#create" => follows, "comment#create" => comments, "article#create" => person_articles, "vote#create" => votes | ||
136 | + } | ||
137 | + | ||
138 | + # ignoring user badges out of environment badges | ||
139 | + should_and_doesnt_have = [] | ||
140 | + should_not_have = [] | ||
141 | + should_have = true | ||
142 | + environment.gamification_plugin_badges.each do |badge| | ||
143 | + (badge.custom_fields || {}).each do |action, config| | ||
144 | + break if scope_by_badge_action[action].nil? or config[:threshold].nil? | ||
145 | + should_have &= scope_by_badge_action[action].count >= config[:threshold].to_i | ||
146 | + end | ||
147 | + have = person.badges.include? badge | ||
148 | + if should_have && !have | ||
149 | + should_and_doesnt_have << "#{badge.title} #{badge.level}" | ||
150 | + elsif should_have && !have | ||
151 | + should_not_have << "#{badge.title} #{badge.level}" | ||
152 | + end | ||
153 | + end | ||
154 | + if should_and_doesnt_have.size > 0 || should_not_have.size > 0 | ||
155 | + CSV.open( "gamification_wrong_badges.csv", 'a' ) do |csv| | ||
156 | + [person.identifier, should_and_doesnt_have.join(' | '), should_not_have.join(' | ')] | ||
157 | + end | ||
158 | + end | ||
159 | + | ||
160 | + scope_by_type = { | ||
161 | + article_author: person_articles, comment_author: comments, vote_voter: votes, follower: follows, | ||
162 | + comment_article_author: comments_received, vote_voteable_author: votes_received, followed_article_author: follows_received | ||
163 | + } | ||
164 | + | ||
165 | + puts "Points:" | ||
166 | + is_profile_clean = true | ||
167 | + scope_by_type.each do |type, scope| | ||
168 | + c = GamificationPlugin::PointsCategorization.for_type(type).where(profile_id: profile_id).joins(:point_type).first | ||
169 | + points = calc_points c, scope | ||
170 | + puts "On #{c.point_type.name} it should have #{points} and have #{person.points(category: c.id.to_s)} " | ||
171 | + if points != person.points(category: c.id.to_s) | ||
172 | + recreate_actions person, scope, c.id.to_s | ||
173 | + points = calc_points c, scope | ||
174 | + if points != person.reload.points(category: c.id.to_s) | ||
175 | + puts "after recreating points the person has: #{person.reload.points(category: c.id.to_s)} and should have #{points}" | ||
176 | + # write to the spreadsheet the person points that couldn't regulate | ||
177 | + CSV.open( "gamification_points_out_expectation.csv", 'a' ) do |csv| | ||
178 | + [person.identifier, person.name, scope.first.class.base_class.name, profile_name, c.id, c.point_type.name, scope.count*c.weight, person.points(category: c.id.to_s)] | ||
179 | + end | ||
180 | + is_profile_clean = false | ||
181 | + else | ||
182 | + puts "points fixed for #{c.point_type.name}!" | ||
183 | + end | ||
184 | + end | ||
185 | + end | ||
186 | + File.open(clean_profiles_file, 'w') {|f| f.write(clean_profiles.push(person.id).to_yaml)} if is_profile_clean | ||
187 | + puts | ||
188 | + end | ||
189 | + end | ||
190 | + | ||
191 | + # update everyone's level after the whole pontuation, | ||
192 | + # which is much faster than on every created action | ||
193 | + environment.people.find_each(batch_size: 100) do |person| | ||
194 | + puts "Updating #{person.identifier} level\n" | ||
195 | + person.update_attribute(:level, person.gamification_plugin_calculate_level) | ||
196 | + end | ||
197 | +end |
script/export_ranking.rb
@@ -37,15 +37,18 @@ profile_ids.each do |profile_id| | @@ -37,15 +37,18 @@ profile_ids.each do |profile_id| | ||
37 | person_down_votes = person.comments.joins(:votes).where('vote < 0').count + person_articles.joins(:votes).where('vote < 0').count | 37 | person_down_votes = person.comments.joins(:votes).where('vote < 0').count + person_articles.joins(:votes).where('vote < 0').count |
38 | person_comments = person.comments.count | 38 | person_comments = person.comments.count |
39 | person_followers = (person.following_articles & person.article_followers.where(article_id: person_articles)).count | 39 | person_followers = (person.following_articles & person.article_followers.where(article_id: person_articles)).count |
40 | + votes = Vote.for_voter(person).count | ||
40 | else | 41 | else |
41 | person_articles = profile.articles.where(:author_id => person.id) | 42 | person_articles = profile.articles.where(:author_id => person.id) |
42 | person_up_votes = person.comments.where(:source_id => profile.articles).joins(:votes).where('vote > 0').count + person_articles.joins(:votes).where('vote > 0').count | 43 | person_up_votes = person.comments.where(:source_id => profile.articles).joins(:votes).where('vote > 0').count + person_articles.joins(:votes).where('vote > 0').count |
43 | person_down_votes = person.comments.where(:source_id => profile.articles).joins(:votes).where('vote < 0').count + person_articles.joins(:votes).where('vote < 0').count | 44 | person_down_votes = person.comments.where(:source_id => profile.articles).joins(:votes).where('vote < 0').count + person_articles.joins(:votes).where('vote < 0').count |
44 | person_comments = person.comments.where(:source_id => profile.articles).count | 45 | person_comments = person.comments.where(:source_id => profile.articles).count |
45 | person_followers = (person.following_articles & person.article_followers.where(article_id: profile.articles)).count | 46 | person_followers = (person.following_articles & person.article_followers.where(article_id: profile.articles)).count |
47 | + the_votes = Vote.for_voter(person) | ||
48 | + votes = the_votes.where(voteable_type: 'Article', voteable_id: profile.articles).count + the_votes.where(voteable_type: 'Comment', voteable_id: Comment.where(source_type: ["ProposalsDiscussionPlugin::Proposal", "Article"], source_id: profile.articles)).count | ||
46 | end | 49 | end |
47 | quantities_values = [ | 50 | quantities_values = [ |
48 | - Vote.for_voter(person).count, | 51 | + votes, |
49 | person.friends.count, | 52 | person.friends.count, |
50 | person_up_votes, | 53 | person_up_votes, |
51 | person_down_votes, | 54 | person_down_votes, |
script/process_merit_rules.rb
@@ -35,13 +35,16 @@ end | @@ -35,13 +35,16 @@ end | ||
35 | # person.sash.destroy unless person.sash.nil? | 35 | # person.sash.destroy unless person.sash.nil? |
36 | #end | 36 | #end |
37 | 37 | ||
38 | +# avoid updating level on every action for increasing performance | ||
39 | +Merit.observers.delete('RankObserver') | ||
40 | + | ||
38 | Merit.observers << 'ProcessObserver' | 41 | Merit.observers << 'ProcessObserver' |
39 | 42 | ||
40 | class Article < ActiveRecord::Base | 43 | class Article < ActiveRecord::Base |
41 | def self.text_article_types | 44 | def self.text_article_types |
42 | # ['TextArticle', 'TextileArticle', 'TinyMceArticle', 'ProposalsDiscussionPlugin::Proposal'] | 45 | # ['TextArticle', 'TextileArticle', 'TinyMceArticle', 'ProposalsDiscussionPlugin::Proposal'] |
43 | ['ProposalsDiscussionPlugin::Proposal'] | 46 | ['ProposalsDiscussionPlugin::Proposal'] |
44 | - end | 47 | + end |
45 | end | 48 | end |
46 | 49 | ||
47 | Environment.all.each do |environment| | 50 | Environment.all.each do |environment| |
@@ -56,7 +59,7 @@ Environment.all.each do |environment| | @@ -56,7 +59,7 @@ Environment.all.each do |environment| | ||
56 | article_index = 0 | 59 | article_index = 0 |
57 | 60 | ||
58 | puts "Amount of articles '#{article_count}'" | 61 | puts "Amount of articles '#{article_count}'" |
59 | - environment.articles.where(:type => Article.text_article_types).find_each do |article| | 62 | + environment.articles.includes(:comments).where(:type => Article.text_article_types).find_each(batch_size: 100) do |article| |
60 | article_index += 1 | 63 | article_index += 1 |
61 | puts "Analising article #{article_index} of #{article_count}" | 64 | puts "Analising article #{article_index} of #{article_count}" |
62 | create_action(article, article_index, article_count) | 65 | create_action(article, article_index, article_count) |
test/functional/gamification_plugin_badges_controller_test.rb
@@ -25,6 +25,14 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase | @@ -25,6 +25,14 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase | ||
25 | end | 25 | end |
26 | end | 26 | end |
27 | 27 | ||
28 | + should "should create gamification_plugin_badge with organization as owner" do | ||
29 | + organization = fast_create(Organization) | ||
30 | + assert_difference('GamificationPlugin::Badge.count') do | ||
31 | + post :create, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | ||
32 | + assert_equal organization, GamificationPlugin::Badge.last.owner | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
28 | should "should show gamification_plugin_badge" do | 36 | should "should show gamification_plugin_badge" do |
29 | get :show, id: @gamification_plugin_badge | 37 | get :show, id: @gamification_plugin_badge |
30 | assert_response :success | 38 | assert_response :success |
@@ -40,6 +48,23 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase | @@ -40,6 +48,23 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase | ||
40 | assert assigns(:gamification_plugin_badge) | 48 | assert assigns(:gamification_plugin_badge) |
41 | end | 49 | end |
42 | 50 | ||
51 | + should "should change badge owner" do | ||
52 | + organization = fast_create(Organization) | ||
53 | + put :update, id: @gamification_plugin_badge, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | ||
54 | + assert assigns(:gamification_plugin_badge) | ||
55 | + assert_equal organization, @gamification_plugin_badge.reload.owner | ||
56 | + end | ||
57 | + | ||
58 | + should "should keep badge owner when update" do | ||
59 | + organization = fast_create(Organization) | ||
60 | + @gamification_plugin_badge.owner = organization | ||
61 | + @gamification_plugin_badge.save! | ||
62 | + | ||
63 | + put :update, id: @gamification_plugin_badge, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | ||
64 | + assert assigns(:gamification_plugin_badge) | ||
65 | + assert_equal organization, @gamification_plugin_badge.reload.owner | ||
66 | + end | ||
67 | + | ||
43 | should "should destroy gamification_plugin_badge" do | 68 | should "should destroy gamification_plugin_badge" do |
44 | assert_difference('GamificationPlugin::Badge.count', -1) do | 69 | assert_difference('GamificationPlugin::Badge.count', -1) do |
45 | delete :destroy, id: @gamification_plugin_badge | 70 | delete :destroy, id: @gamification_plugin_badge |
test/functional/gamification_plugin_profile_controller_test.rb
@@ -11,12 +11,13 @@ class GamificationPluginProfileControllerTest < ActionController::TestCase | @@ -11,12 +11,13 @@ class GamificationPluginProfileControllerTest < ActionController::TestCase | ||
11 | attr_accessor :person, :environment | 11 | attr_accessor :person, :environment |
12 | 12 | ||
13 | should 'display points in gamification dashboard' do | 13 | should 'display points in gamification dashboard' do |
14 | - person.add_points(20, :category => :comment_author) | ||
15 | - person.add_points(30, :category => :article_author) | 14 | + create_all_point_rules |
15 | + article = create(TextArticle, :profile_id => fast_create(Community).id, :author => person) | ||
16 | + create(Comment, :source => article, :author_id => create_user.person.id) | ||
16 | get :dashboard, :profile => person.identifier | 17 | get :dashboard, :profile => person.identifier |
17 | - assert_tag :div, :attributes => {:class => 'score article_author positive'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '30'} | ||
18 | - assert_tag :div, :attributes => {:class => 'score comment_author positive'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '20'} | ||
19 | - assert_tag :div, :attributes => {:class => 'score total'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '50'} | 18 | + assert_tag :div, :attributes => {:class => 'score article_author positive do_action'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => default_point_weight(:article_author).to_s} |
19 | + assert_tag :div, :attributes => {:class => 'score comment_article_author positive do_action'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => default_point_weight(:comment_article_author).to_s} | ||
20 | + assert_tag :div, :attributes => {:class => 'score total'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => (default_point_weight(:comment_article_author) + default_point_weight(:article_author)).to_s} | ||
20 | end | 21 | end |
21 | 22 | ||
22 | should 'display level in gamification dashboard' do | 23 | should 'display level in gamification dashboard' do |
@@ -33,7 +34,7 @@ class GamificationPluginProfileControllerTest < ActionController::TestCase | @@ -33,7 +34,7 @@ class GamificationPluginProfileControllerTest < ActionController::TestCase | ||
33 | person.add_badge(badge1.id) | 34 | person.add_badge(badge1.id) |
34 | person.add_badge(badge2.id) | 35 | person.add_badge(badge2.id) |
35 | get :dashboard, :profile => person.identifier | 36 | get :dashboard, :profile => person.identifier |
36 | - assert_select '.badges .badge-list .badge', 1 | 37 | + assert_select '.badges .badge-list li.badge', 1 |
37 | end | 38 | end |
38 | 39 | ||
39 | end | 40 | end |
test/test_helper.rb
@@ -15,6 +15,10 @@ def create_all_point_rules | @@ -15,6 +15,10 @@ def create_all_point_rules | ||
15 | end | 15 | end |
16 | end | 16 | end |
17 | 17 | ||
18 | +def default_point_weight(rule_name) | ||
19 | + Merit::PointRules::AVAILABLE_RULES[rule_name][:default_weight] | ||
20 | +end | ||
21 | + | ||
18 | def load_point_rule(rule_name, config) | 22 | def load_point_rule(rule_name, config) |
19 | rule_config = Merit::PointRules::AVAILABLE_RULES[rule_name.to_sym] | 23 | rule_config = Merit::PointRules::AVAILABLE_RULES[rule_name.to_sym] |
20 | raise "Point rule '#{rule_name}' is not available" if rule_config.nil? | 24 | raise "Point rule '#{rule_name}' is not available" if rule_config.nil? |
@@ -22,7 +26,7 @@ def load_point_rule(rule_name, config) | @@ -22,7 +26,7 @@ def load_point_rule(rule_name, config) | ||
22 | rule_config | 26 | rule_config |
23 | end | 27 | end |
24 | 28 | ||
25 | -#person_points_debug(person) | 29 | +#person_points_debug(person) |
26 | def person_points_debug(person) | 30 | def person_points_debug(person) |
27 | person.score_points.map do |sp| | 31 | person.score_points.map do |sp| |
28 | puts 'Ponto:' | 32 | puts 'Ponto:' |
test/unit/api_test.rb
@@ -8,6 +8,7 @@ class APITest < ActiveSupport::TestCase | @@ -8,6 +8,7 @@ class APITest < ActiveSupport::TestCase | ||
8 | environment = Environment.default | 8 | environment = Environment.default |
9 | environment.enable_plugin(GamificationPlugin) | 9 | environment.enable_plugin(GamificationPlugin) |
10 | GamificationPlugin.gamification_set_rules(@environment) | 10 | GamificationPlugin.gamification_set_rules(@environment) |
11 | + create_all_point_rules | ||
11 | end | 12 | end |
12 | 13 | ||
13 | should 'get my own badges' do | 14 | should 'get my own badges' do |
@@ -27,14 +28,6 @@ class APITest < ActiveSupport::TestCase | @@ -27,14 +28,6 @@ class APITest < ActiveSupport::TestCase | ||
27 | assert_not_nil json['percent'] | 28 | assert_not_nil json['percent'] |
28 | end | 29 | end |
29 | 30 | ||
30 | - should 'get my total pontuation' do | ||
31 | - badge = GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') | ||
32 | - person.add_badge(badge.id) | ||
33 | - get "/api/v1/gamification_plugin/my/points?#{params.to_query}" | ||
34 | - json = JSON.parse(last_response.body) | ||
35 | - assert_not_nil json['points'] | ||
36 | - end | ||
37 | - | ||
38 | should 'get badges of the public person' do | 31 | should 'get badges of the public person' do |
39 | badge = GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') | 32 | badge = GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') |
40 | another_person = create(User, :environment => environment).person | 33 | another_person = create(User, :environment => environment).person |
@@ -63,7 +56,7 @@ class APITest < ActiveSupport::TestCase | @@ -63,7 +56,7 @@ class APITest < ActiveSupport::TestCase | ||
63 | another_person.save | 56 | another_person.save |
64 | another_person.add_badge(badge.id) | 57 | another_person.add_badge(badge.id) |
65 | get "/api/v1/gamification_plugin/people/#{another_person.id}/badges?#{params.to_query}" | 58 | get "/api/v1/gamification_plugin/people/#{another_person.id}/badges?#{params.to_query}" |
66 | - json = JSON.parse(last_response.body) | 59 | + JSON.parse(last_response.body) |
67 | assert_equal 404, last_response.status | 60 | assert_equal 404, last_response.status |
68 | end | 61 | end |
69 | 62 | ||
@@ -76,4 +69,115 @@ class APITest < ActiveSupport::TestCase | @@ -76,4 +69,115 @@ class APITest < ActiveSupport::TestCase | ||
76 | assert_equal 404, last_response.status | 69 | assert_equal 404, last_response.status |
77 | end | 70 | end |
78 | 71 | ||
72 | + should 'get amount of environment badges grouped by name' do | ||
73 | + 3.times { GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') } | ||
74 | + get "/api/v1/gamification_plugin/badges" | ||
75 | + json = JSON.parse(last_response.body) | ||
76 | + assert_equal 3, json['test_badge'] | ||
77 | + end | ||
78 | + | ||
79 | + should 'get my points' do | ||
80 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | ||
81 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | ||
82 | + | ||
83 | + process_delayed_job_queue | ||
84 | + | ||
85 | + get "/api/v1/gamification_plugin/my/points?#{params.to_query}" | ||
86 | + json = JSON.parse(last_response.body) | ||
87 | + assert_equal default_point_weight(:article_author) + default_point_weight(:comment_article_author), json['points'] | ||
88 | + end | ||
89 | + | ||
90 | + should 'get my points filtered by type' do | ||
91 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | ||
92 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | ||
93 | + | ||
94 | + process_delayed_job_queue | ||
95 | + | ||
96 | + params[:type] = 'article_author' | ||
97 | + | ||
98 | + get "/api/v1/gamification_plugin/my/points_by_type?#{params.to_query}" | ||
99 | + json = JSON.parse(last_response.body) | ||
100 | + assert_equal default_point_weight(:article_author), json['points'] | ||
101 | + end | ||
102 | + | ||
103 | + should 'get my points filtered by profile' do | ||
104 | + community = fast_create(Community) | ||
105 | + create_point_rule_definition('article_author', community) | ||
106 | + create(TextArticle, :profile_id => @person.id, :author => @person) | ||
107 | + create(TextArticle, :profile_id => community.id, :author => @person) | ||
108 | + | ||
109 | + process_delayed_job_queue | ||
110 | + | ||
111 | + params[:profile] = community.identifier | ||
112 | + | ||
113 | + get "/api/v1/gamification_plugin/my/points_by_profile?#{params.to_query}" | ||
114 | + json = JSON.parse(last_response.body) | ||
115 | + assert_equal default_point_weight(:article_author), json['points'] | ||
116 | + end | ||
117 | + | ||
118 | + should 'get my points excluding points earned in profiles' do | ||
119 | + community = fast_create(Community) | ||
120 | + create_point_rule_definition('article_author', community) | ||
121 | + create(TextArticle, :profile_id => @person.id, :author => @person) | ||
122 | + create(TextArticle, :profile_id => community.id, :author => @person) | ||
123 | + | ||
124 | + process_delayed_job_queue | ||
125 | + | ||
126 | + get "/api/v1/gamification_plugin/my/points_out_of_profiles?#{params.to_query}" | ||
127 | + json = JSON.parse(last_response.body) | ||
128 | + assert_equal 2*default_point_weight(:article_author), json['points'] | ||
129 | + end | ||
130 | + | ||
131 | + should 'get points of a person' do | ||
132 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | ||
133 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | ||
134 | + | ||
135 | + process_delayed_job_queue | ||
136 | + | ||
137 | + get "/api/v1/gamification_plugin/people/#{person.id}/points?#{params.to_query}" | ||
138 | + json = JSON.parse(last_response.body) | ||
139 | + assert_equal default_point_weight(:article_author) + default_point_weight(:comment_article_author), json['points'] | ||
140 | + end | ||
141 | + | ||
142 | + should 'get points of a person filtered by type' do | ||
143 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | ||
144 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | ||
145 | + | ||
146 | + process_delayed_job_queue | ||
147 | + | ||
148 | + params[:type] = 'article_author' | ||
149 | + | ||
150 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_by_type?#{params.to_query}" | ||
151 | + json = JSON.parse(last_response.body) | ||
152 | + assert_equal default_point_weight(:article_author), json['points'] | ||
153 | + end | ||
154 | + | ||
155 | + should 'get points of a person filtered by profile' do | ||
156 | + community = fast_create(Community) | ||
157 | + create_point_rule_definition('article_author', community) | ||
158 | + create(TextArticle, :profile_id => @person.id, :author => @person) | ||
159 | + create(TextArticle, :profile_id => community.id, :author => @person) | ||
160 | + | ||
161 | + process_delayed_job_queue | ||
162 | + | ||
163 | + params[:profile] = community.identifier | ||
164 | + | ||
165 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_by_profile?#{params.to_query}" | ||
166 | + json = JSON.parse(last_response.body) | ||
167 | + assert_equal default_point_weight(:article_author), json['points'] | ||
168 | + end | ||
169 | + | ||
170 | + should 'get points of a person excluding points earned in profiles' do | ||
171 | + community = fast_create(Community) | ||
172 | + create_point_rule_definition('article_author', community) | ||
173 | + create(TextArticle, :profile_id => @person.id, :author => @person) | ||
174 | + create(TextArticle, :profile_id => community.id, :author => @person) | ||
175 | + | ||
176 | + process_delayed_job_queue | ||
177 | + | ||
178 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_out_of_profiles?#{params.to_query}" | ||
179 | + json = JSON.parse(last_response.body) | ||
180 | + assert_equal 2*default_point_weight(:article_author), json['points'] | ||
181 | + end | ||
182 | + | ||
79 | end | 183 | end |
test/unit/article_follower_test.rb
@@ -14,9 +14,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -14,9 +14,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
14 | create_point_rule_definition('followed_article') | 14 | create_point_rule_definition('followed_article') |
15 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 15 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
16 | 16 | ||
17 | + process_delayed_job_queue | ||
18 | + | ||
17 | c = GamificationPlugin::PointsCategorization.for_type(:followed_article).first | 19 | c = GamificationPlugin::PointsCategorization.for_type(:followed_article).first |
18 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do | 20 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do |
19 | article.person_followers << person | 21 | article.person_followers << person |
22 | + process_delayed_job_queue | ||
20 | end | 23 | end |
21 | end | 24 | end |
22 | 25 | ||
@@ -25,9 +28,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -25,9 +28,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
25 | 28 | ||
26 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 29 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
27 | 30 | ||
31 | + process_delayed_job_queue | ||
32 | + | ||
28 | c = GamificationPlugin::PointsCategorization.for_type(:follower).first | 33 | c = GamificationPlugin::PointsCategorization.for_type(:follower).first |
29 | assert_difference 'person.points(:category => c.id.to_s)', c.weight do | 34 | assert_difference 'person.points(:category => c.id.to_s)', c.weight do |
30 | article.person_followers << person | 35 | article.person_followers << person |
36 | + process_delayed_job_queue | ||
31 | end | 37 | end |
32 | end | 38 | end |
33 | 39 | ||
@@ -36,9 +42,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -36,9 +42,12 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
36 | 42 | ||
37 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 43 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
38 | 44 | ||
45 | + process_delayed_job_queue | ||
46 | + | ||
39 | c = GamificationPlugin::PointsCategorization.for_type(:followed_article_author).first | 47 | c = GamificationPlugin::PointsCategorization.for_type(:followed_article_author).first |
40 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 48 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
41 | article.person_followers << person | 49 | article.person_followers << person |
50 | + process_delayed_job_queue | ||
42 | end | 51 | end |
43 | end | 52 | end |
44 | 53 | ||
@@ -46,11 +55,18 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -46,11 +55,18 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
46 | create_point_rule_definition('follower') | 55 | create_point_rule_definition('follower') |
47 | follower = create_user('someuser').person | 56 | follower = create_user('someuser').person |
48 | article = create(TextArticle, :profile_id => community.id, :author => person) | 57 | article = create(TextArticle, :profile_id => community.id, :author => person) |
58 | + | ||
59 | + process_delayed_job_queue | ||
60 | + | ||
49 | score_points = follower.score_points.count | 61 | score_points = follower.score_points.count |
50 | points = follower.points | 62 | points = follower.points |
51 | article.person_followers << follower | 63 | article.person_followers << follower |
64 | + process_delayed_job_queue | ||
65 | + | ||
52 | assert_equal score_points + 1, follower.score_points.count | 66 | assert_equal score_points + 1, follower.score_points.count |
53 | ArticleFollower.last.destroy | 67 | ArticleFollower.last.destroy |
68 | + process_delayed_job_queue | ||
69 | + | ||
54 | assert_equal score_points + 2, follower.score_points.count | 70 | assert_equal score_points + 2, follower.score_points.count |
55 | assert_equal points, follower.points | 71 | assert_equal points, follower.points |
56 | end | 72 | end |
@@ -58,9 +74,13 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -58,9 +74,13 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
58 | should 'subtract merit points to article author when a user unfollow an article' do | 74 | should 'subtract merit points to article author when a user unfollow an article' do |
59 | create_point_rule_definition('follower') | 75 | create_point_rule_definition('follower') |
60 | article = create(TextArticle, :profile_id => community.id, :author => person) | 76 | article = create(TextArticle, :profile_id => community.id, :author => person) |
77 | + | ||
78 | + process_delayed_job_queue | ||
79 | + | ||
61 | assert_no_difference 'person.points' do | 80 | assert_no_difference 'person.points' do |
62 | assert_difference 'person.score_points.count' do | 81 | assert_difference 'person.score_points.count' do |
63 | article.person_followers << fast_create(Person) | 82 | article.person_followers << fast_create(Person) |
83 | + process_delayed_job_queue | ||
64 | end | 84 | end |
65 | assert_difference 'person.score_points.count' do | 85 | assert_difference 'person.score_points.count' do |
66 | ArticleFollower.last.destroy | 86 | ArticleFollower.last.destroy |
@@ -71,11 +91,16 @@ class ArticleFollowerTest < ActiveSupport::TestCase | @@ -71,11 +91,16 @@ class ArticleFollowerTest < ActiveSupport::TestCase | ||
71 | should 'subtract merit points to article when a user unfollow an article' do | 91 | should 'subtract merit points to article when a user unfollow an article' do |
72 | create_point_rule_definition('followed_article') | 92 | create_point_rule_definition('followed_article') |
73 | article = create(TextArticle, :profile_id => community.id, :author => person) | 93 | article = create(TextArticle, :profile_id => community.id, :author => person) |
94 | + process_delayed_job_queue | ||
74 | score_points = article.score_points.count | 95 | score_points = article.score_points.count |
75 | points = article.points | 96 | points = article.points |
76 | article.person_followers << person | 97 | article.person_followers << person |
98 | + process_delayed_job_queue | ||
99 | + | ||
77 | assert_equal score_points + 1, article.score_points.count | 100 | assert_equal score_points + 1, article.score_points.count |
78 | ArticleFollower.last.destroy | 101 | ArticleFollower.last.destroy |
102 | + process_delayed_job_queue | ||
103 | + | ||
79 | assert_equal score_points + 2, article.score_points.count | 104 | assert_equal score_points + 2, article.score_points.count |
80 | assert_equal points, article.points | 105 | assert_equal points, article.points |
81 | end | 106 | end |
test/unit/article_test.rb
@@ -12,6 +12,7 @@ class ArticleTest < ActiveSupport::TestCase | @@ -12,6 +12,7 @@ class ArticleTest < ActiveSupport::TestCase | ||
12 | should 'add merit points to author when create a new article' do | 12 | should 'add merit points to author when create a new article' do |
13 | create_point_rule_definition('article_author') | 13 | create_point_rule_definition('article_author') |
14 | create(TextArticle, :profile_id => person.id, :author => person) | 14 | create(TextArticle, :profile_id => person.id, :author => person) |
15 | + process_delayed_job_queue | ||
15 | assert_equal 1, person.score_points.count | 16 | assert_equal 1, person.score_points.count |
16 | assert person.score_points.first.action.present? | 17 | assert person.score_points.first.action.present? |
17 | end | 18 | end |
@@ -19,8 +20,10 @@ class ArticleTest < ActiveSupport::TestCase | @@ -19,8 +20,10 @@ class ArticleTest < ActiveSupport::TestCase | ||
19 | should 'subtract merit points to author when destroy an article' do | 20 | should 'subtract merit points to author when destroy an article' do |
20 | create_point_rule_definition('article_author') | 21 | create_point_rule_definition('article_author') |
21 | article = create(TextArticle, :profile_id => person.id, :author => person) | 22 | article = create(TextArticle, :profile_id => person.id, :author => person) |
23 | + process_delayed_job_queue | ||
22 | assert_equal 1, person.score_points.count | 24 | assert_equal 1, person.score_points.count |
23 | article.destroy | 25 | article.destroy |
26 | + process_delayed_job_queue | ||
24 | assert_equal 2, person.score_points.count | 27 | assert_equal 2, person.score_points.count |
25 | assert_equal 0, person.points | 28 | assert_equal 0, person.points |
26 | end | 29 | end |
@@ -30,6 +33,7 @@ class ArticleTest < ActiveSupport::TestCase | @@ -30,6 +33,7 @@ class ArticleTest < ActiveSupport::TestCase | ||
30 | GamificationPlugin.gamification_set_rules(environment) | 33 | GamificationPlugin.gamification_set_rules(environment) |
31 | 34 | ||
32 | 5.times { create(TextArticle, :profile_id => person.id, :author => person) } | 35 | 5.times { create(TextArticle, :profile_id => person.id, :author => person) } |
36 | + process_delayed_job_queue | ||
33 | assert_equal 'article_author', person.badges.first.name | 37 | assert_equal 'article_author', person.badges.first.name |
34 | assert_equal 1, person.badges.first.level | 38 | assert_equal 1, person.badges.first.level |
35 | end | 39 | end |
@@ -40,6 +44,8 @@ class ArticleTest < ActiveSupport::TestCase | @@ -40,6 +44,8 @@ class ArticleTest < ActiveSupport::TestCase | ||
40 | GamificationPlugin.gamification_set_rules(environment) | 44 | GamificationPlugin.gamification_set_rules(environment) |
41 | 45 | ||
42 | 10.times { create(TextArticle, :profile_id => person.id, :author => person) } | 46 | 10.times { create(TextArticle, :profile_id => person.id, :author => person) } |
47 | + process_delayed_job_queue | ||
48 | + sleep 4 | ||
43 | assert_equal ['article_author'], person.badges.map(&:name).uniq | 49 | assert_equal ['article_author'], person.badges.map(&:name).uniq |
44 | assert_equal [1, 2], person.badges.map(&:level) | 50 | assert_equal [1, 2], person.badges.map(&:level) |
45 | end | 51 | end |
@@ -48,49 +54,59 @@ class ArticleTest < ActiveSupport::TestCase | @@ -48,49 +54,59 @@ class ArticleTest < ActiveSupport::TestCase | ||
48 | create_point_rule_definition('vote_voteable_author') | 54 | create_point_rule_definition('vote_voteable_author') |
49 | community = fast_create(Community) | 55 | community = fast_create(Community) |
50 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 56 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
57 | + process_delayed_job_queue | ||
51 | 58 | ||
52 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 59 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
53 | - assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | ||
54 | - Vote.create!(:voter => person, :voteable => article, :vote => 1) | ||
55 | - end | 60 | + points = article.author.points(:category => c.id.to_s) |
61 | + Vote.create!(:voter => person, :voteable => article, :vote => 1) | ||
62 | + process_delayed_job_queue | ||
63 | + assert_equal article.author.points(:category => c.id.to_s), points + c.weight | ||
56 | end | 64 | end |
57 | 65 | ||
58 | should 'add merit points to article when an user like it' do | 66 | should 'add merit points to article when an user like it' do |
59 | create_point_rule_definition('vote_voteable') | 67 | create_point_rule_definition('vote_voteable') |
60 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) | 68 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) |
69 | + process_delayed_job_queue | ||
61 | article = article.reload | 70 | article = article.reload |
62 | 71 | ||
63 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable).first | 72 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable).first |
64 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do | 73 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do |
65 | Vote.create!(:voter => person, :voteable => article, :vote => 1) | 74 | Vote.create!(:voter => person, :voteable => article, :vote => 1) |
75 | + process_delayed_job_queue | ||
66 | end | 76 | end |
67 | end | 77 | end |
68 | 78 | ||
69 | should 'add merit points to community when create a new article' do | 79 | should 'add merit points to community when create a new article' do |
70 | create_point_rule_definition('article_community') | 80 | create_point_rule_definition('article_community') |
71 | community = fast_create(Community) | 81 | community = fast_create(Community) |
82 | + process_delayed_job_queue | ||
72 | assert_difference 'community.score_points.count' do | 83 | assert_difference 'community.score_points.count' do |
73 | create(TextArticle, :profile_id => community.id, :author => person) | 84 | create(TextArticle, :profile_id => community.id, :author => person) |
85 | + process_delayed_job_queue | ||
74 | end | 86 | end |
75 | end | 87 | end |
76 | 88 | ||
77 | should 'add merit points to voter when he likes an article' do | 89 | should 'add merit points to voter when he likes an article' do |
78 | create_point_rule_definition('vote_voter') | 90 | create_point_rule_definition('vote_voter') |
79 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) | 91 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) |
92 | + process_delayed_job_queue | ||
80 | 93 | ||
81 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 94 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
82 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 95 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
83 | Vote.create!(:voter => person, :voteable => article, :vote => 1) | 96 | Vote.create!(:voter => person, :voteable => article, :vote => 1) |
97 | + process_delayed_job_queue | ||
84 | end | 98 | end |
85 | end | 99 | end |
86 | 100 | ||
87 | should 'add merit points to voter when he dislikes an article' do | 101 | should 'add merit points to voter when he dislikes an article' do |
88 | create_point_rule_definition('vote_voter') | 102 | create_point_rule_definition('vote_voter') |
89 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) | 103 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) |
104 | + process_delayed_job_queue | ||
90 | 105 | ||
91 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 106 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
92 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 107 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
93 | Vote.create!(:voter => person, :voteable => article, :vote => -1) | 108 | Vote.create!(:voter => person, :voteable => article, :vote => -1) |
109 | + process_delayed_job_queue | ||
94 | end | 110 | end |
95 | end | 111 | end |
96 | 112 | ||
@@ -101,8 +117,10 @@ class ArticleTest < ActiveSupport::TestCase | @@ -101,8 +117,10 @@ class ArticleTest < ActiveSupport::TestCase | ||
101 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) | 117 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) |
102 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) } | 118 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) } |
103 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) | 119 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) |
120 | + process_delayed_job_queue | ||
104 | assert_equal [], person.badges | 121 | assert_equal [], person.badges |
105 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) | 122 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) |
123 | + process_delayed_job_queue | ||
106 | assert_equal 'positive_votes_received', person.reload.badges.first.name | 124 | assert_equal 'positive_votes_received', person.reload.badges.first.name |
107 | end | 125 | end |
108 | 126 | ||
@@ -113,8 +131,10 @@ class ArticleTest < ActiveSupport::TestCase | @@ -113,8 +131,10 @@ class ArticleTest < ActiveSupport::TestCase | ||
113 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) | 131 | article = create(TextArticle, :name => 'Test', :profile => person, :author => person) |
114 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) } | 132 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) } |
115 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) | 133 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => 1) |
134 | + process_delayed_job_queue | ||
116 | assert_equal [], person.badges | 135 | assert_equal [], person.badges |
117 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) | 136 | Vote.create!(:voter => fast_create(Person), :voteable => article, :vote => -1) |
137 | + process_delayed_job_queue | ||
118 | assert_equal 'negative_votes_received', person.reload.badges.first.name | 138 | assert_equal 'negative_votes_received', person.reload.badges.first.name |
119 | end | 139 | end |
120 | 140 | ||
@@ -123,6 +143,7 @@ class ArticleTest < ActiveSupport::TestCase | @@ -123,6 +143,7 @@ class ArticleTest < ActiveSupport::TestCase | ||
123 | community = fast_create(Community) | 143 | community = fast_create(Community) |
124 | rule = create_point_rule_definition('article_author', community) | 144 | rule = create_point_rule_definition('article_author', community) |
125 | create(TextArticle, profile_id: community.id, author_id: person.id) | 145 | create(TextArticle, profile_id: community.id, author_id: person.id) |
146 | + process_delayed_job_queue | ||
126 | assert_equal rule.weight, person.points_by_profile(community.identifier) | 147 | assert_equal rule.weight, person.points_by_profile(community.identifier) |
127 | assert person.score_points.first.action.present? | 148 | assert person.score_points.first.action.present? |
128 | end | 149 | end |
@@ -131,8 +152,10 @@ class ArticleTest < ActiveSupport::TestCase | @@ -131,8 +152,10 @@ class ArticleTest < ActiveSupport::TestCase | ||
131 | community = fast_create(Community) | 152 | community = fast_create(Community) |
132 | rule = create_point_rule_definition('article_author', community) | 153 | rule = create_point_rule_definition('article_author', community) |
133 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 154 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
155 | + process_delayed_job_queue | ||
134 | assert_equal rule.weight, person.points_by_profile(community.identifier) | 156 | assert_equal rule.weight, person.points_by_profile(community.identifier) |
135 | article.destroy | 157 | article.destroy |
158 | + process_delayed_job_queue | ||
136 | assert_equal 0, person.points | 159 | assert_equal 0, person.points |
137 | end | 160 | end |
138 | 161 | ||
@@ -140,10 +163,12 @@ class ArticleTest < ActiveSupport::TestCase | @@ -140,10 +163,12 @@ class ArticleTest < ActiveSupport::TestCase | ||
140 | community = fast_create(Community) | 163 | community = fast_create(Community) |
141 | create_point_rule_definition('vote_voteable_author', community) | 164 | create_point_rule_definition('vote_voteable_author', community) |
142 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 165 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
166 | + process_delayed_job_queue | ||
143 | 167 | ||
144 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 168 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
145 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 169 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
146 | Vote.create!(:voter => person, :voteable => article, :vote => 1) | 170 | Vote.create!(:voter => person, :voteable => article, :vote => 1) |
171 | + process_delayed_job_queue | ||
147 | end | 172 | end |
148 | end | 173 | end |
149 | 174 | ||
@@ -151,19 +176,23 @@ class ArticleTest < ActiveSupport::TestCase | @@ -151,19 +176,23 @@ class ArticleTest < ActiveSupport::TestCase | ||
151 | community = fast_create(Community) | 176 | community = fast_create(Community) |
152 | create_point_rule_definition('vote_voteable', community) | 177 | create_point_rule_definition('vote_voteable', community) |
153 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 178 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
179 | + process_delayed_job_queue | ||
154 | article = article.reload | 180 | article = article.reload |
155 | 181 | ||
156 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable).first | 182 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable).first |
157 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do | 183 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do |
158 | Vote.create!(:voter => person, :voteable => article, :vote => 1) | 184 | Vote.create!(:voter => person, :voteable => article, :vote => 1) |
185 | + process_delayed_job_queue | ||
159 | end | 186 | end |
160 | end | 187 | end |
161 | 188 | ||
162 | should 'add merit points to community when create a new article on community' do | 189 | should 'add merit points to community when create a new article on community' do |
163 | community = fast_create(Community) | 190 | community = fast_create(Community) |
164 | create_point_rule_definition('article_community') | 191 | create_point_rule_definition('article_community') |
192 | + process_delayed_job_queue | ||
165 | assert_difference 'community.score_points.count' do | 193 | assert_difference 'community.score_points.count' do |
166 | create(TextArticle, :profile_id => community.id, :author => person) | 194 | create(TextArticle, :profile_id => community.id, :author => person) |
195 | + process_delayed_job_queue | ||
167 | end | 196 | end |
168 | end | 197 | end |
169 | 198 | ||
@@ -171,10 +200,12 @@ class ArticleTest < ActiveSupport::TestCase | @@ -171,10 +200,12 @@ class ArticleTest < ActiveSupport::TestCase | ||
171 | community = fast_create(Community) | 200 | community = fast_create(Community) |
172 | create_point_rule_definition('vote_voter', community) | 201 | create_point_rule_definition('vote_voter', community) |
173 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 202 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
203 | + process_delayed_job_queue | ||
174 | 204 | ||
175 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 205 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
176 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 206 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
177 | Vote.create!(:voter => person, :voteable => article, :vote => 1) | 207 | Vote.create!(:voter => person, :voteable => article, :vote => 1) |
208 | + process_delayed_job_queue | ||
178 | end | 209 | end |
179 | end | 210 | end |
180 | 211 | ||
@@ -182,11 +213,35 @@ class ArticleTest < ActiveSupport::TestCase | @@ -182,11 +213,35 @@ class ArticleTest < ActiveSupport::TestCase | ||
182 | community = fast_create(Community) | 213 | community = fast_create(Community) |
183 | create_point_rule_definition('vote_voter', community) | 214 | create_point_rule_definition('vote_voter', community) |
184 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) | 215 | article = create(TextArticle, :name => 'Test', :profile => community, :author => person) |
216 | + process_delayed_job_queue | ||
185 | 217 | ||
186 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 218 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
187 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do | 219 | assert_difference 'article.author.points(:category => c.id.to_s)', c.weight do |
188 | Vote.create!(:voter => person, :voteable => article, :vote => -1) | 220 | Vote.create!(:voter => person, :voteable => article, :vote => -1) |
221 | + process_delayed_job_queue | ||
189 | end | 222 | end |
190 | end | 223 | end |
191 | 224 | ||
225 | + should "add organization's merit badge to author when create 5 new articles" do | ||
226 | + organization = fast_create(Organization) | ||
227 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'article_author', :level => 1) | ||
228 | + GamificationPlugin.gamification_set_rules(environment) | ||
229 | + | ||
230 | + 5.times { create(TextArticle, :profile_id => organization.id, :author => person) } | ||
231 | + process_delayed_job_queue | ||
232 | + assert_equal 'article_author', person.badges.first.name | ||
233 | + assert_equal 1, person.badges.first.level | ||
234 | + end | ||
235 | + | ||
236 | + should "do not earn organization's badge when the article is not posted in the organization itself" do | ||
237 | + organization = fast_create(Organization) | ||
238 | + other_organization = fast_create(Organization) | ||
239 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'article_author', :level => 1) | ||
240 | + GamificationPlugin.gamification_set_rules(environment) | ||
241 | + | ||
242 | + 5.times { create(TextArticle, :profile_id => other_organization.id, :author => person) } | ||
243 | + process_delayed_job_queue | ||
244 | + assert_equal [], person.badges | ||
245 | + end | ||
246 | + | ||
192 | end | 247 | end |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | + | ||
3 | +class BadgeRulesTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @environment = Environment.default | ||
7 | + end | ||
8 | + | ||
9 | + attr_accessor :environment | ||
10 | + | ||
11 | + should "define badge rules for environment's badges" do | ||
12 | + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author) | ||
13 | + badge_rules = Merit::BadgeRules.new(environment) | ||
14 | + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first[:action]], badge_rules.defined_rules.keys | ||
15 | + end | ||
16 | + | ||
17 | + should "define badge rules for organization's badges" do | ||
18 | + organization = fast_create(Organization) | ||
19 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | ||
20 | + badge_rules = Merit::BadgeRules.new(environment) | ||
21 | + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first[:action]], badge_rules.defined_rules.keys | ||
22 | + end | ||
23 | + | ||
24 | + should 'check organization returns true when badge belongs to the environment' do | ||
25 | + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author) | ||
26 | + badge_rules = Merit::BadgeRules.new(environment) | ||
27 | + comment = fast_create(Comment) | ||
28 | + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first) | ||
29 | + end | ||
30 | + | ||
31 | + should 'check organization returns true when the comment belongs to the organization' do | ||
32 | + organization = fast_create(Organization) | ||
33 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | ||
34 | + badge_rules = Merit::BadgeRules.new(environment) | ||
35 | + article = fast_create(Article,:profile_id => organization.id) | ||
36 | + comment = fast_create(Comment, :source_id => article.id) | ||
37 | + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first) | ||
38 | + end | ||
39 | + | ||
40 | + should 'check organization returns false when the comment does not belongs to the organization' do | ||
41 | + organization = fast_create(Organization) | ||
42 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | ||
43 | + badge_rules = Merit::BadgeRules.new(environment) | ||
44 | + comment = fast_create(Comment) | ||
45 | + assert !badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first) | ||
46 | + end | ||
47 | + | ||
48 | +end |
test/unit/badge_test.rb
@@ -5,9 +5,10 @@ class BadgeTest < ActiveSupport::TestCase | @@ -5,9 +5,10 @@ class BadgeTest < ActiveSupport::TestCase | ||
5 | def setup | 5 | def setup |
6 | @person = create_user('testuser').person | 6 | @person = create_user('testuser').person |
7 | @environment = Environment.default | 7 | @environment = Environment.default |
8 | + @organization = fast_create(Organization) | ||
8 | end | 9 | end |
9 | 10 | ||
10 | - attr_accessor :person, :environment | 11 | + attr_accessor :person, :environment, :organization |
11 | 12 | ||
12 | should 'add badge to person' do | 13 | should 'add badge to person' do |
13 | badge = GamificationPlugin::Badge.create!(:owner => environment) | 14 | badge = GamificationPlugin::Badge.create!(:owner => environment) |
@@ -37,4 +38,16 @@ class BadgeTest < ActiveSupport::TestCase | @@ -37,4 +38,16 @@ class BadgeTest < ActiveSupport::TestCase | ||
37 | assert_equal [badge2], person.badges.notification_pending | 38 | assert_equal [badge2], person.badges.notification_pending |
38 | end | 39 | end |
39 | 40 | ||
41 | + should 'add badge to person with organization as the badge owner' do | ||
42 | + badge = GamificationPlugin::Badge.create(:owner => organization) | ||
43 | + person.add_badge(badge.id) | ||
44 | + assert_equal [badge], person.badges | ||
45 | + end | ||
46 | + | ||
47 | + should 'add a manual badge to person' do | ||
48 | + badge = GamificationPlugin::Badge.create!(:name => :manual, :owner => environment) | ||
49 | + person.add_badge(badge.id) | ||
50 | + assert_equal [badge], person.badges | ||
51 | + end | ||
52 | + | ||
40 | end | 53 | end |
test/unit/comment_test.rb
@@ -13,14 +13,17 @@ class CommentTest < ActiveSupport::TestCase | @@ -13,14 +13,17 @@ class CommentTest < ActiveSupport::TestCase | ||
13 | should 'add merit points to author when create a new comment' do | 13 | should 'add merit points to author when create a new comment' do |
14 | create_point_rule_definition('comment_author') | 14 | create_point_rule_definition('comment_author') |
15 | create(Comment, :source => article, :author_id => person.id) | 15 | create(Comment, :source => article, :author_id => person.id) |
16 | + process_delayed_job_queue | ||
16 | assert_equal 1, person.score_points.count | 17 | assert_equal 1, person.score_points.count |
17 | end | 18 | end |
18 | 19 | ||
19 | should 'subtract merit points from author when destroy a comment' do | 20 | should 'subtract merit points from author when destroy a comment' do |
20 | create_point_rule_definition('comment_author') | 21 | create_point_rule_definition('comment_author') |
21 | comment = create(Comment, :source => article, :author_id => person.id) | 22 | comment = create(Comment, :source => article, :author_id => person.id) |
23 | + process_delayed_job_queue | ||
22 | assert_equal 1, person.score_points.count | 24 | assert_equal 1, person.score_points.count |
23 | comment.destroy | 25 | comment.destroy |
26 | + process_delayed_job_queue | ||
24 | assert_equal 2, person.score_points.count | 27 | assert_equal 2, person.score_points.count |
25 | assert_equal 0, person.points | 28 | assert_equal 0, person.points |
26 | end | 29 | end |
@@ -30,6 +33,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -30,6 +33,7 @@ class CommentTest < ActiveSupport::TestCase | ||
30 | GamificationPlugin.gamification_set_rules(environment) | 33 | GamificationPlugin.gamification_set_rules(environment) |
31 | 34 | ||
32 | 5.times { create(Comment, :source => article, :author_id => person.id) } | 35 | 5.times { create(Comment, :source => article, :author_id => person.id) } |
36 | + process_delayed_job_queue | ||
33 | assert_equal 'comment_author', person.badges.first.name | 37 | assert_equal 'comment_author', person.badges.first.name |
34 | end | 38 | end |
35 | 39 | ||
@@ -38,6 +42,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -38,6 +42,7 @@ class CommentTest < ActiveSupport::TestCase | ||
38 | GamificationPlugin.gamification_set_rules(environment) | 42 | GamificationPlugin.gamification_set_rules(environment) |
39 | 43 | ||
40 | 5.times { create(Comment, :source => article, :author_id => person.id) } | 44 | 5.times { create(Comment, :source => article, :author_id => person.id) } |
45 | + process_delayed_job_queue | ||
41 | assert_equal 'comment_received', author.badges.first.name | 46 | assert_equal 'comment_received', author.badges.first.name |
42 | end | 47 | end |
43 | 48 | ||
@@ -48,8 +53,10 @@ class CommentTest < ActiveSupport::TestCase | @@ -48,8 +53,10 @@ class CommentTest < ActiveSupport::TestCase | ||
48 | comment = create(Comment, :source => article, :author_id => person.id) | 53 | comment = create(Comment, :source => article, :author_id => person.id) |
49 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) } | 54 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) } |
50 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) | 55 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) |
56 | + process_delayed_job_queue | ||
51 | assert_equal [], person.badges | 57 | assert_equal [], person.badges |
52 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) | 58 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) |
59 | + process_delayed_job_queue | ||
53 | assert_equal 'positive_votes_received', person.reload.badges.first.name | 60 | assert_equal 'positive_votes_received', person.reload.badges.first.name |
54 | end | 61 | end |
55 | 62 | ||
@@ -60,18 +67,22 @@ class CommentTest < ActiveSupport::TestCase | @@ -60,18 +67,22 @@ class CommentTest < ActiveSupport::TestCase | ||
60 | comment = create(Comment, :source => article, :author_id => person.id) | 67 | comment = create(Comment, :source => article, :author_id => person.id) |
61 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) } | 68 | 4.times { Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) } |
62 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) | 69 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => 1) |
70 | + process_delayed_job_queue | ||
63 | assert_equal [], person.badges | 71 | assert_equal [], person.badges |
64 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) | 72 | Vote.create!(:voter => fast_create(Person), :voteable => comment, :vote => -1) |
73 | + process_delayed_job_queue | ||
65 | assert_equal 'negative_votes_received', person.reload.badges.first.name | 74 | assert_equal 'negative_votes_received', person.reload.badges.first.name |
66 | end | 75 | end |
67 | 76 | ||
68 | should 'add merit points to comment owner when an user like his comment' do | 77 | should 'add merit points to comment owner when an user like his comment' do |
69 | create_point_rule_definition('vote_voteable_author') | 78 | create_point_rule_definition('vote_voteable_author') |
70 | comment = create(Comment, :source => article, :author_id => person.id) | 79 | comment = create(Comment, :source => article, :author_id => person.id) |
80 | + process_delayed_job_queue | ||
71 | 81 | ||
72 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 82 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
73 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 83 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
74 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 84 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
85 | + process_delayed_job_queue | ||
75 | end | 86 | end |
76 | end | 87 | end |
77 | 88 | ||
@@ -79,20 +90,24 @@ class CommentTest < ActiveSupport::TestCase | @@ -79,20 +90,24 @@ class CommentTest < ActiveSupport::TestCase | ||
79 | create_point_rule_definition('vote_voteable_author') | 90 | create_point_rule_definition('vote_voteable_author') |
80 | comment = create(Comment, :source => article, :author_id => author.id) | 91 | comment = create(Comment, :source => article, :author_id => author.id) |
81 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 92 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
93 | + process_delayed_job_queue | ||
82 | 94 | ||
83 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 95 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
84 | assert_difference 'comment.author.points', -1*c.weight do | 96 | assert_difference 'comment.author.points', -1*c.weight do |
85 | Vote.where(:voteable_id => comment.id).destroy_all | 97 | Vote.where(:voteable_id => comment.id).destroy_all |
98 | + process_delayed_job_queue | ||
86 | end | 99 | end |
87 | end | 100 | end |
88 | 101 | ||
89 | should 'subtract merit points from comment owner when an user dislike his comment' do | 102 | should 'subtract merit points from comment owner when an user dislike his comment' do |
90 | create_point_rule_definition('vote_voteable_author') | 103 | create_point_rule_definition('vote_voteable_author') |
91 | comment = create(Comment, :source => article, :author_id => person.id) | 104 | comment = create(Comment, :source => article, :author_id => person.id) |
105 | + process_delayed_job_queue | ||
92 | 106 | ||
93 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 107 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
94 | assert_difference 'comment.author.points(:category => c.id.to_s)', -1*c.weight do | 108 | assert_difference 'comment.author.points(:category => c.id.to_s)', -1*c.weight do |
95 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 109 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
110 | + process_delayed_job_queue | ||
96 | end | 111 | end |
97 | end | 112 | end |
98 | 113 | ||
@@ -100,37 +115,44 @@ class CommentTest < ActiveSupport::TestCase | @@ -100,37 +115,44 @@ class CommentTest < ActiveSupport::TestCase | ||
100 | create_point_rule_definition('vote_voteable_author') | 115 | create_point_rule_definition('vote_voteable_author') |
101 | comment = create(Comment, :source => article, :author_id => author.id) | 116 | comment = create(Comment, :source => article, :author_id => author.id) |
102 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 117 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
118 | + process_delayed_job_queue | ||
103 | 119 | ||
104 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 120 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
105 | assert_difference 'comment.author.points', c.weight do | 121 | assert_difference 'comment.author.points', c.weight do |
106 | Vote.where(:voteable_id => comment.id).destroy_all | 122 | Vote.where(:voteable_id => comment.id).destroy_all |
123 | + process_delayed_job_queue | ||
107 | end | 124 | end |
108 | end | 125 | end |
109 | 126 | ||
110 | should 'add merit points to article author when create a new comment' do | 127 | should 'add merit points to article author when create a new comment' do |
111 | create_point_rule_definition('comment_article_author') | 128 | create_point_rule_definition('comment_article_author') |
112 | - assert_difference 'author.score_points.count' do | ||
113 | - create(Comment, :source => article, :author_id => person.id) | ||
114 | - end | 129 | + scores = author.score_points.count |
130 | + create(Comment, :source => article, :author_id => person.id) | ||
131 | + process_delayed_job_queue | ||
132 | + assert_not_equal author.reload.score_points.count, scores | ||
115 | end | 133 | end |
116 | 134 | ||
117 | should 'add merit points to voter when he likes a comment' do | 135 | should 'add merit points to voter when he likes a comment' do |
118 | create_point_rule_definition('vote_voter') | 136 | create_point_rule_definition('vote_voter') |
119 | comment = create(Comment, :source => article, :author_id => person.id) | 137 | comment = create(Comment, :source => article, :author_id => person.id) |
138 | + process_delayed_job_queue | ||
120 | 139 | ||
121 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 140 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
122 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 141 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
123 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 142 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
143 | + process_delayed_job_queue | ||
124 | end | 144 | end |
125 | end | 145 | end |
126 | 146 | ||
127 | should 'add merit points to voter when he dislikes a comment' do | 147 | should 'add merit points to voter when he dislikes a comment' do |
128 | create_point_rule_definition('vote_voter') | 148 | create_point_rule_definition('vote_voter') |
129 | comment = create(Comment, :source => article, :author_id => person.id) | 149 | comment = create(Comment, :source => article, :author_id => person.id) |
150 | + process_delayed_job_queue | ||
130 | 151 | ||
131 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 152 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
132 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 153 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
133 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 154 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
155 | + process_delayed_job_queue | ||
134 | end | 156 | end |
135 | end | 157 | end |
136 | 158 | ||
@@ -139,6 +161,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -139,6 +161,7 @@ class CommentTest < ActiveSupport::TestCase | ||
139 | c = GamificationPlugin::PointsCategorization.for_type(:comment_article).first | 161 | c = GamificationPlugin::PointsCategorization.for_type(:comment_article).first |
140 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do | 162 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do |
141 | create(Comment, :source => article, :author_id => person.id) | 163 | create(Comment, :source => article, :author_id => person.id) |
164 | + process_delayed_job_queue | ||
142 | end | 165 | end |
143 | end | 166 | end |
144 | 167 | ||
@@ -146,10 +169,12 @@ class CommentTest < ActiveSupport::TestCase | @@ -146,10 +169,12 @@ class CommentTest < ActiveSupport::TestCase | ||
146 | create_point_rule_definition('comment_community') | 169 | create_point_rule_definition('comment_community') |
147 | community = fast_create(Community) | 170 | community = fast_create(Community) |
148 | article = create(TextileArticle, :profile_id => community.id, :author_id => author.id) | 171 | article = create(TextileArticle, :profile_id => community.id, :author_id => author.id) |
172 | + process_delayed_job_queue | ||
149 | 173 | ||
150 | c = GamificationPlugin::PointsCategorization.for_type(:comment_community).first | 174 | c = GamificationPlugin::PointsCategorization.for_type(:comment_community).first |
151 | assert_difference 'community.points(:category => c.id.to_s)', c.weight do | 175 | assert_difference 'community.points(:category => c.id.to_s)', c.weight do |
152 | create(Comment, :source => article, :author_id => person.id) | 176 | create(Comment, :source => article, :author_id => person.id) |
177 | + process_delayed_job_queue | ||
153 | end | 178 | end |
154 | end | 179 | end |
155 | 180 | ||
@@ -157,8 +182,10 @@ class CommentTest < ActiveSupport::TestCase | @@ -157,8 +182,10 @@ class CommentTest < ActiveSupport::TestCase | ||
157 | should 'add merit community points to author when create a new comment in a community' do | 182 | should 'add merit community points to author when create a new comment in a community' do |
158 | community = fast_create(Community) | 183 | community = fast_create(Community) |
159 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 184 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
185 | + process_delayed_job_queue | ||
160 | rule = create_point_rule_definition('comment_author', article.profile) | 186 | rule = create_point_rule_definition('comment_author', article.profile) |
161 | create(Comment, :source => article, :author_id => person.id) | 187 | create(Comment, :source => article, :author_id => person.id) |
188 | + process_delayed_job_queue | ||
162 | assert_equal rule.weight, person.points_by_profile(article.profile.identifier) | 189 | assert_equal rule.weight, person.points_by_profile(article.profile.identifier) |
163 | end | 190 | end |
164 | 191 | ||
@@ -167,6 +194,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -167,6 +194,7 @@ class CommentTest < ActiveSupport::TestCase | ||
167 | article = create(TextArticle, profile_id: community.id, author_id: fast_create(Person).id) | 194 | article = create(TextArticle, profile_id: community.id, author_id: fast_create(Person).id) |
168 | rule = create_point_rule_definition('comment_author', article.profile) | 195 | rule = create_point_rule_definition('comment_author', article.profile) |
169 | comment = create(Comment, :source => article, :author_id => person.id) | 196 | comment = create(Comment, :source => article, :author_id => person.id) |
197 | + process_delayed_job_queue | ||
170 | assert_equal rule.weight, person.points_by_profile(article.profile.identifier) | 198 | assert_equal rule.weight, person.points_by_profile(article.profile.identifier) |
171 | comment.destroy | 199 | comment.destroy |
172 | assert_equal 0, person.points_by_profile(article.profile.identifier) | 200 | assert_equal 0, person.points_by_profile(article.profile.identifier) |
@@ -177,10 +205,12 @@ class CommentTest < ActiveSupport::TestCase | @@ -177,10 +205,12 @@ class CommentTest < ActiveSupport::TestCase | ||
177 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 205 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
178 | create_point_rule_definition('vote_voteable_author', community) | 206 | create_point_rule_definition('vote_voteable_author', community) |
179 | comment = create(Comment, :source => article, :author_id => person.id) | 207 | comment = create(Comment, :source => article, :author_id => person.id) |
208 | + process_delayed_job_queue | ||
180 | 209 | ||
181 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).where(profile_id: article.profile.id).first | 210 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).where(profile_id: article.profile.id).first |
182 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 211 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
183 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 212 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
213 | + process_delayed_job_queue | ||
184 | end | 214 | end |
185 | end | 215 | end |
186 | 216 | ||
@@ -190,6 +220,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -190,6 +220,7 @@ class CommentTest < ActiveSupport::TestCase | ||
190 | create_point_rule_definition('vote_voteable_author', community) | 220 | create_point_rule_definition('vote_voteable_author', community) |
191 | comment = create(Comment, :source => article, :author_id => author.id) | 221 | comment = create(Comment, :source => article, :author_id => author.id) |
192 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 222 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
223 | + process_delayed_job_queue | ||
193 | 224 | ||
194 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 225 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
195 | assert_difference 'comment.author.points_by_profile(community.identifier)', -1*c.weight do | 226 | assert_difference 'comment.author.points_by_profile(community.identifier)', -1*c.weight do |
@@ -202,10 +233,12 @@ class CommentTest < ActiveSupport::TestCase | @@ -202,10 +233,12 @@ class CommentTest < ActiveSupport::TestCase | ||
202 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 233 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
203 | create_point_rule_definition('vote_voteable_author', community) | 234 | create_point_rule_definition('vote_voteable_author', community) |
204 | comment = create(Comment, :source => article, :author_id => person.id) | 235 | comment = create(Comment, :source => article, :author_id => person.id) |
236 | + process_delayed_job_queue | ||
205 | 237 | ||
206 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).where(profile_id: article.profile.id).first | 238 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).where(profile_id: article.profile.id).first |
207 | assert_difference 'comment.author.points(:category => c.id.to_s)', -1*c.weight do | 239 | assert_difference 'comment.author.points(:category => c.id.to_s)', -1*c.weight do |
208 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 240 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
241 | + process_delayed_job_queue | ||
209 | end | 242 | end |
210 | end | 243 | end |
211 | 244 | ||
@@ -215,6 +248,7 @@ class CommentTest < ActiveSupport::TestCase | @@ -215,6 +248,7 @@ class CommentTest < ActiveSupport::TestCase | ||
215 | create_point_rule_definition('vote_voteable_author', community) | 248 | create_point_rule_definition('vote_voteable_author', community) |
216 | comment = create(Comment, :source => article, :author_id => author.id) | 249 | comment = create(Comment, :source => article, :author_id => author.id) |
217 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 250 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
251 | + process_delayed_job_queue | ||
218 | 252 | ||
219 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first | 253 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voteable_author).first |
220 | assert_difference 'comment.author.points_by_profile(community.identifier)', c.weight do | 254 | assert_difference 'comment.author.points_by_profile(community.identifier)', c.weight do |
@@ -225,9 +259,11 @@ class CommentTest < ActiveSupport::TestCase | @@ -225,9 +259,11 @@ class CommentTest < ActiveSupport::TestCase | ||
225 | should 'add merit community points to article author when create a new comment inside a community' do | 259 | should 'add merit community points to article author when create a new comment inside a community' do |
226 | community = fast_create(Community) | 260 | community = fast_create(Community) |
227 | article = create(TextArticle, profile_id: community.id, author_id: author.id) | 261 | article = create(TextArticle, profile_id: community.id, author_id: author.id) |
262 | + process_delayed_job_queue | ||
228 | rule = create_point_rule_definition('comment_article_author', community) | 263 | rule = create_point_rule_definition('comment_article_author', community) |
229 | assert_difference 'author.points_by_profile(community.identifier)', rule.weight do | 264 | assert_difference 'author.points_by_profile(community.identifier)', rule.weight do |
230 | create(Comment, :source => article, :author_id => author.id) | 265 | create(Comment, :source => article, :author_id => author.id) |
266 | + process_delayed_job_queue | ||
231 | end | 267 | end |
232 | end | 268 | end |
233 | 269 | ||
@@ -236,10 +272,12 @@ class CommentTest < ActiveSupport::TestCase | @@ -236,10 +272,12 @@ class CommentTest < ActiveSupport::TestCase | ||
236 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 272 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
237 | create_point_rule_definition('vote_voter') | 273 | create_point_rule_definition('vote_voter') |
238 | comment = create(Comment, :source => article, :author_id => person.id) | 274 | comment = create(Comment, :source => article, :author_id => person.id) |
275 | + process_delayed_job_queue | ||
239 | 276 | ||
240 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 277 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
241 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 278 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
242 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) | 279 | Vote.create!(:voter => person, :voteable => comment, :vote => 1) |
280 | + process_delayed_job_queue | ||
243 | end | 281 | end |
244 | end | 282 | end |
245 | 283 | ||
@@ -248,20 +286,24 @@ class CommentTest < ActiveSupport::TestCase | @@ -248,20 +286,24 @@ class CommentTest < ActiveSupport::TestCase | ||
248 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 286 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
249 | create_point_rule_definition('vote_voter') | 287 | create_point_rule_definition('vote_voter') |
250 | comment = create(Comment, :source => article, :author_id => person.id) | 288 | comment = create(Comment, :source => article, :author_id => person.id) |
289 | + process_delayed_job_queue | ||
251 | 290 | ||
252 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first | 291 | c = GamificationPlugin::PointsCategorization.for_type(:vote_voter).first |
253 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do | 292 | assert_difference 'comment.author.points(:category => c.id.to_s)', c.weight do |
254 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) | 293 | Vote.create!(:voter => person, :voteable => comment, :vote => -1) |
294 | + process_delayed_job_queue | ||
255 | end | 295 | end |
256 | end | 296 | end |
257 | 297 | ||
258 | should 'add merit community points to source article when create a comment inside a community' do | 298 | should 'add merit community points to source article when create a comment inside a community' do |
259 | community = fast_create(Community) | 299 | community = fast_create(Community) |
260 | article = create(TextArticle, profile_id: community.id, author_id: person.id) | 300 | article = create(TextArticle, profile_id: community.id, author_id: person.id) |
301 | + process_delayed_job_queue | ||
261 | create_point_rule_definition('comment_article') | 302 | create_point_rule_definition('comment_article') |
262 | c = GamificationPlugin::PointsCategorization.for_type(:comment_article).first | 303 | c = GamificationPlugin::PointsCategorization.for_type(:comment_article).first |
263 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do | 304 | assert_difference 'article.points(:category => c.id.to_s)', c.weight do |
264 | create(Comment, :source => article, :author_id => person.id) | 305 | create(Comment, :source => article, :author_id => person.id) |
306 | + process_delayed_job_queue | ||
265 | end | 307 | end |
266 | end | 308 | end |
267 | 309 | ||
@@ -269,12 +311,24 @@ class CommentTest < ActiveSupport::TestCase | @@ -269,12 +311,24 @@ class CommentTest < ActiveSupport::TestCase | ||
269 | create_point_rule_definition('comment_community') | 311 | create_point_rule_definition('comment_community') |
270 | community = fast_create(Community) | 312 | community = fast_create(Community) |
271 | article = create(TextileArticle, :profile_id => community.id, :author_id => author.id) | 313 | article = create(TextileArticle, :profile_id => community.id, :author_id => author.id) |
314 | + process_delayed_job_queue | ||
272 | 315 | ||
273 | c = GamificationPlugin::PointsCategorization.for_type(:comment_community).first | 316 | c = GamificationPlugin::PointsCategorization.for_type(:comment_community).first |
274 | assert_difference 'community.points(:category => c.id.to_s)', c.weight do | 317 | assert_difference 'community.points(:category => c.id.to_s)', c.weight do |
275 | create(Comment, :source => article, :author_id => person.id) | 318 | create(Comment, :source => article, :author_id => person.id) |
319 | + process_delayed_job_queue | ||
276 | end | 320 | end |
277 | end | 321 | end |
278 | 322 | ||
323 | + should "add organization's merit badge to author when create 5 new comments" do | ||
324 | + organization = fast_create(Organization) | ||
325 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'comment_author') | ||
326 | + GamificationPlugin.gamification_set_rules(environment) | ||
327 | + article.profile = organization | ||
328 | + | ||
329 | + 5.times { create(Comment, :source => article, :author_id => person.id) } | ||
330 | + process_delayed_job_queue | ||
331 | + assert_equal 'comment_author', person.badges.first.name | ||
332 | + end | ||
279 | 333 | ||
280 | end | 334 | end |
@@ -0,0 +1,34 @@ | @@ -0,0 +1,34 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | + | ||
3 | +class DashboardHelperTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + include GamificationPlugin::DashboardHelper | ||
6 | + | ||
7 | + should 'return title for global badges' do | ||
8 | + owner = Environment.new | ||
9 | + assert_equal 'Badges', badges_title(owner) | ||
10 | + end | ||
11 | + | ||
12 | + should 'return title for organization badges' do | ||
13 | + owner = Organization.new(:name => 'organization') | ||
14 | + assert_equal 'Badges for organization', badges_title(owner) | ||
15 | + end | ||
16 | + | ||
17 | + should 'return badges grouped by owner' do | ||
18 | + environment = Environment.default | ||
19 | + expects(:environment).at_least_once.returns(environment) | ||
20 | + badge1 = GamificationPlugin::Badge.create!(:owner => fast_create(Organization)) | ||
21 | + badge2 = GamificationPlugin::Badge.create!(:owner => environment) | ||
22 | + assert_equal [[badge2.owner, [badge2]], [badge1.owner, [badge1]]], grouped_badges | ||
23 | + end | ||
24 | + | ||
25 | + should 'return category of a score point' do | ||
26 | + point_type = GamificationPlugin::PointsType.create!(name: "point category", description: "point category") | ||
27 | + score = Merit::Score.new | ||
28 | + score.category = point_type.id.to_s | ||
29 | + score.save! | ||
30 | + point = score.score_points.create! | ||
31 | + assert_equal "point category", score_point_category(point) | ||
32 | + end | ||
33 | + | ||
34 | +end |
test/unit/gamification_plugin_test.rb
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | + | ||
3 | +class MeritExtTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'check if the point was originated by an undo action' do | ||
6 | + point = Merit::Score::Point.new | ||
7 | + point_type = GamificationPlugin::PointsType.new(name: :comment_author) | ||
8 | + point.expects(:point_type).returns(point_type) | ||
9 | + action = mock | ||
10 | + action.expects(:target_model).returns('comment') | ||
11 | + action.expects(:action_method).returns('destroy') | ||
12 | + point.expects(:action).at_least_once.returns(action) | ||
13 | + assert point.undo_rule? | ||
14 | + end | ||
15 | + | ||
16 | + should 'check if the point was originated by a do action' do | ||
17 | + point = Merit::Score::Point.new | ||
18 | + point_type = GamificationPlugin::PointsType.new(name: :comment_author) | ||
19 | + point.expects(:point_type).returns(point_type) | ||
20 | + action = mock | ||
21 | + action.expects(:target_model).returns('comment') | ||
22 | + action.expects(:action_method).returns('create') | ||
23 | + point.expects(:action).at_least_once.returns(action) | ||
24 | + assert !point.undo_rule? | ||
25 | + end | ||
26 | + | ||
27 | +end |
test/unit/person_test.rb
@@ -13,8 +13,10 @@ class PersonTest < ActiveSupport::TestCase | @@ -13,8 +13,10 @@ class PersonTest < ActiveSupport::TestCase | ||
13 | GamificationPlugin.gamification_set_rules(environment) | 13 | GamificationPlugin.gamification_set_rules(environment) |
14 | 14 | ||
15 | 4.times { Vote.create!(:voter => person, :voteable => fast_create(Comment), :vote => 1) } | 15 | 4.times { Vote.create!(:voter => person, :voteable => fast_create(Comment), :vote => 1) } |
16 | + process_delayed_job_queue | ||
16 | assert_equal [], person.badges | 17 | assert_equal [], person.badges |
17 | Vote.create!(:voter => person, :voteable => fast_create(Comment), :vote => 1) | 18 | Vote.create!(:voter => person, :voteable => fast_create(Comment), :vote => 1) |
19 | + process_delayed_job_queue | ||
18 | assert_equal 'votes_performed', person.reload.badges.first.name | 20 | assert_equal 'votes_performed', person.reload.badges.first.name |
19 | end | 21 | end |
20 | 22 | ||
@@ -23,6 +25,7 @@ class PersonTest < ActiveSupport::TestCase | @@ -23,6 +25,7 @@ class PersonTest < ActiveSupport::TestCase | ||
23 | GamificationPlugin.gamification_set_rules(environment) | 25 | GamificationPlugin.gamification_set_rules(environment) |
24 | 26 | ||
25 | 5.times { |i| person.add_friend(create_user("testuser#{i}").person) } | 27 | 5.times { |i| person.add_friend(create_user("testuser#{i}").person) } |
28 | + process_delayed_job_queue | ||
26 | assert_equal 'friendly', person.reload.badges.first.name | 29 | assert_equal 'friendly', person.reload.badges.first.name |
27 | end | 30 | end |
28 | 31 | ||
@@ -30,6 +33,7 @@ class PersonTest < ActiveSupport::TestCase | @@ -30,6 +33,7 @@ class PersonTest < ActiveSupport::TestCase | ||
30 | create_point_rule_definition('friends') | 33 | create_point_rule_definition('friends') |
31 | other_person = create_user("testuserfriend").person | 34 | other_person = create_user("testuserfriend").person |
32 | person.add_friend(other_person) | 35 | person.add_friend(other_person) |
36 | + process_delayed_job_queue | ||
33 | c = GamificationPlugin::PointsCategorization.for_type(:friends).first | 37 | c = GamificationPlugin::PointsCategorization.for_type(:friends).first |
34 | assert_equal 5, person.score_points(:category => c.id.to_s).sum(:num_points) | 38 | assert_equal 5, person.score_points(:category => c.id.to_s).sum(:num_points) |
35 | end | 39 | end |
test/unit/point_rules_test.rb
@@ -19,4 +19,23 @@ class PointRulesTest < ActiveSupport::TestCase | @@ -19,4 +19,23 @@ class PointRulesTest < ActiveSupport::TestCase | ||
19 | assert point_rules.defined_rules.present? | 19 | assert point_rules.defined_rules.present? |
20 | end | 20 | end |
21 | 21 | ||
22 | + should 'return target url for a point related to article creation' do | ||
23 | + person = create_user('testuser').person | ||
24 | + create_point_rule_definition('article_author') | ||
25 | + article = create(TextArticle, :profile_id => person.id, :author => person) | ||
26 | + process_delayed_job_queue | ||
27 | + url = Merit::PointRules.target_url(person.score_points.last) | ||
28 | + assert_equal article.url, url | ||
29 | + end | ||
30 | + | ||
31 | + should 'return target url for a point related to comment creation' do | ||
32 | + person = create_user('testuser').person | ||
33 | + create_point_rule_definition('comment_author') | ||
34 | + article = create(Article, :profile_id => person.id, :author => person) | ||
35 | + comment = create(Comment, :source_id => article.id, :author => person) | ||
36 | + process_delayed_job_queue | ||
37 | + url = Merit::PointRules.target_url(person.score_points.last) | ||
38 | + assert_equal comment.url, url | ||
39 | + end | ||
40 | + | ||
22 | end | 41 | end |
test/unit/profile_test.rb
@@ -50,6 +50,7 @@ class ProfileTest < ActiveSupport::TestCase | @@ -50,6 +50,7 @@ class ProfileTest < ActiveSupport::TestCase | ||
50 | Person.any_instance.stubs(:is_profile_complete?).returns(true) | 50 | Person.any_instance.stubs(:is_profile_complete?).returns(true) |
51 | create_point_rule_definition('profile_completion', nil, {value: 0}) | 51 | create_point_rule_definition('profile_completion', nil, {value: 0}) |
52 | GamificationPlugin.gamification_set_rules(environment) | 52 | GamificationPlugin.gamification_set_rules(environment) |
53 | + process_delayed_job_queue | ||
53 | assert_equal 0, person.level | 54 | assert_equal 0, person.level |
54 | assert_nothing_raised do | 55 | assert_nothing_raised do |
55 | person.save | 56 | person.save |
@@ -62,8 +63,10 @@ class ProfileTest < ActiveSupport::TestCase | @@ -62,8 +63,10 @@ class ProfileTest < ActiveSupport::TestCase | ||
62 | GamificationPlugin.gamification_set_rules(environment) | 63 | GamificationPlugin.gamification_set_rules(environment) |
63 | 64 | ||
64 | person = create_user('testuser').person | 65 | person = create_user('testuser').person |
66 | + process_delayed_job_queue | ||
65 | assert_equal 0, person.level | 67 | assert_equal 0, person.level |
66 | create(TextArticle, :profile_id => community.id, :author => person) | 68 | create(TextArticle, :profile_id => community.id, :author => person) |
69 | + process_delayed_job_queue | ||
67 | assert_equal 3, person.reload.level | 70 | assert_equal 3, person.reload.level |
68 | end | 71 | end |
69 | 72 |
views/gamification/_ranking.html.erb
1 | -<% if ranking.empty? %> | 1 | +<% if ranking.blank? %> |
2 | <div class="ranking-empty"><%= _('Not enough points for this ranking yet') %></div> | 2 | <div class="ranking-empty"><%= _('Not enough points for this ranking yet') %></div> |
3 | <% else %> | 3 | <% else %> |
4 | <ul class="ranking <%= defined?(ranking_class) ? ranking_class : '' %>"> | 4 | <ul class="ranking <%= defined?(ranking_class) ? ranking_class : '' %>"> |
views/gamification/dashboard.html.erb
@@ -22,9 +22,9 @@ | @@ -22,9 +22,9 @@ | ||
22 | <div class="scores"> | 22 | <div class="scores"> |
23 | <h3><%= _('Latest Score Points') %></h3> | 23 | <h3><%= _('Latest Score Points') %></h3> |
24 | <% @target.score_points.order('created_at desc').limit(5).each do |point| %> | 24 | <% @target.score_points.order('created_at desc').limit(5).each do |point| %> |
25 | - <div class="score <%= point.score.category %> <%= score_point_class(point) %>"> | 25 | + <div class="score <%= point.point_type.name %> <%= score_point_class(point) %> <%= score_point_action_class(point) %>"> |
26 | <span class="value"><%= point.num_points %></span> | 26 | <span class="value"><%= point.num_points %></span> |
27 | - <span class="category"><%= _(score_point_category(point)) %></span> | 27 | + <span class="category"><%= score_point_target_link point, _(score_point_category(point)) %></span> |
28 | <span class="date timeago" title="<%= point.created_at %>"><%= point.created_at %></span> | 28 | <span class="date timeago" title="<%= point.created_at %>"><%= point.created_at %></span> |
29 | </div> | 29 | </div> |
30 | <% end %> | 30 | <% end %> |
@@ -34,24 +34,26 @@ | @@ -34,24 +34,26 @@ | ||
34 | 34 | ||
35 | <% unless environment.gamification_plugin_badges.empty? %> | 35 | <% unless environment.gamification_plugin_badges.empty? %> |
36 | <div class="badges"> | 36 | <div class="badges"> |
37 | - <h3><%= _('Badges') %></h3> | ||
38 | - <ul class="badge-list"> | ||
39 | - <% environment.gamification_plugin_badges.group(:name).count.each do |badge_name, amount| %> | ||
40 | - <% person_badge = @target.badges.where(:name => badge_name).last %> | ||
41 | - <% badge = environment.gamification_plugin_badges.where(:name => badge_name).last %> | ||
42 | - <li class="badge <%= badge.name %>"> | ||
43 | - <div class="badge" title="<%= badge.description %>"> | ||
44 | - <div class="image <%= badge.name %>"></div> | ||
45 | - <ul class="level rating"> | ||
46 | - <% 1.upto(badge.level).map do |n|%> | ||
47 | - <span class="star <%= (person_badge && person_badge.level >= n) ? 'earned' : 'not-earned' %>" >★</span> | ||
48 | - <% end %> | ||
49 | - </ul> | ||
50 | - <div class="title"><%= badge.title %></div> | ||
51 | - </div> | ||
52 | - </li> | 37 | + <% grouped_badges.each do |owner, badges| %> |
38 | + <h3><%= badges_title owner %></h3> | ||
39 | + <ul class="badge-list"> | ||
40 | + <% badges.group_by(&:name).each do |badge_name, badges_group| %> | ||
41 | + <% badge = badges_group.sort_by(&:level).last %> | ||
42 | + <% person_badge = @target.badges.where(:name => badge.name).last %> | ||
43 | + <li class="badge <%= badge.name %>"> | ||
44 | + <div class="badge" title="<%= badge.description %>"> | ||
45 | + <div class="image <%= badge.name %>"></div> | ||
46 | + <ul class="level rating"> | ||
47 | + <% 1.upto(badge.level).map do |n|%> | ||
48 | + <span class="star <%= (person_badge && person_badge.level >= n) ? 'earned' : 'not-earned' %>" >★</span> | ||
49 | + <% end %> | ||
50 | + </ul> | ||
51 | + <div class="title"><%= badge.title %></div> | ||
52 | + </div> | ||
53 | + </li> | ||
54 | + <% end %> | ||
55 | + </ul> | ||
53 | <% end %> | 56 | <% end %> |
54 | - </ul> | ||
55 | </div> | 57 | </div> |
56 | <% end %> | 58 | <% end %> |
57 | </div> | 59 | </div> |
views/gamification_plugin_badges/_form.html.erb
@@ -29,24 +29,31 @@ | @@ -29,24 +29,31 @@ | ||
29 | <%= f.label :level %><br /> | 29 | <%= f.label :level %><br /> |
30 | <%= f.text_field :level %> | 30 | <%= f.text_field :level %> |
31 | </div> | 31 | </div> |
32 | - <h4><%= _('Actions') %></h4> | ||
33 | - <%= f.fields_for :custom_fields do |c| %> | ||
34 | - <% rules.each do |name, settings| %> | ||
35 | - <div class='controller-actions <%= "name_#{name}" %>'> | ||
36 | - <% settings.each do |setting| %> | ||
37 | - <%= c.label _(setting[:action]) %> | ||
38 | - <%= c.fields_for setting[:action] do |d| %> | ||
39 | - <% action = (@gamification_plugin_badge.custom_fields || {}).fetch(setting[:action], {}) %> | ||
40 | - <div class="field"> | ||
41 | - <%= d.label :threshold %><br /> | ||
42 | - <%= d.text_field :threshold, {value: action.fetch('threshold', "")} %> | ||
43 | - </div> | ||
44 | - <br> | 32 | + <div class="field"> |
33 | + <%= f.label :profile_owner %><br /> | ||
34 | + <% tokenized_owner = @gamification_plugin_badge.owner.present? && @gamification_plugin_badge.owner.kind_of?(Organization) ? prepare_to_token_input([@gamification_plugin_badge.owner]) : nil %> | ||
35 | + <%= token_input_field_tag('gamification_plugin_badge[owner_id]', 'badge-owner', {:action => 'search_owners'}, {:focus => false, :hint_text => _('Choose a profile or leave it blank for a global badge'), :token_limit => 1, :pre_populate => tokenized_owner}) %> | ||
36 | + </div> | ||
37 | + <div class="action-fields"> | ||
38 | + <h4><%= _('Actions') %></h4> | ||
39 | + <%= f.fields_for :custom_fields do |c| %> | ||
40 | + <% rules.each do |name, settings| %> | ||
41 | + <div class='controller-actions <%= "name_#{name}" %>'> | ||
42 | + <% settings.select {|s| s[:action].present?}.each do |setting| %> | ||
43 | + <%= c.label _(setting[:action]) %> | ||
44 | + <%= c.fields_for setting[:action] do |d| %> | ||
45 | + <% action = (@gamification_plugin_badge.custom_fields || {}).fetch(setting[:action], {}) %> | ||
46 | + <div class="field"> | ||
47 | + <%= d.label :threshold %><br /> | ||
48 | + <%= d.text_field :threshold, {value: action.fetch('threshold', "")} %> | ||
49 | + </div> | ||
50 | + <br> | ||
51 | + <% end %> | ||
45 | <% end %> | 52 | <% end %> |
46 | - <% end %> | ||
47 | - </div> | 53 | + </div> |
54 | + <% end %> | ||
48 | <% end %> | 55 | <% end %> |
49 | - <% end %> | 56 | + </div> |
50 | <div class="actions"> | 57 | <div class="actions"> |
51 | <%= f.submit %> | 58 | <%= f.submit %> |
52 | </div> | 59 | </div> |
views/gamification_plugin_badges/index.html.erb
1 | +<%= stylesheet_link_tag 'plugins/gamification/admin.css' %> | ||
2 | + | ||
1 | <h1><%= _('Gamification Settings: Listing Badges') %></h1> | 3 | <h1><%= _('Gamification Settings: Listing Badges') %></h1> |
2 | 4 | ||
3 | -<table> | 5 | +<table class="gamification-plugin-badges"> |
4 | <tr> | 6 | <tr> |
5 | <th>Name</th> | 7 | <th>Name</th> |
6 | <th>Title</th> | 8 | <th>Title</th> |
@@ -10,7 +12,11 @@ | @@ -10,7 +12,11 @@ | ||
10 | <th></th> | 12 | <th></th> |
11 | </tr> | 13 | </tr> |
12 | 14 | ||
13 | -<% @gamification_plugin_badges.each do |gamification_plugin_badge| %> | 15 | +<% @gamification_plugin_badges.each do |owner, badges| %> |
16 | + <% if owner.present? %> | ||
17 | + <tr><td class="badge-owner-group" colspan="6"><%= _("Badges for:") %> <%= owner.name %></td></tr> | ||
18 | + <% end %> | ||
19 | + <% badges.each do |gamification_plugin_badge| %> | ||
14 | <tr> | 20 | <tr> |
15 | <td><%= gamification_plugin_badge.name %></td> | 21 | <td><%= gamification_plugin_badge.name %></td> |
16 | <td><%= gamification_plugin_badge.title %></td> | 22 | <td><%= gamification_plugin_badge.title %></td> |
@@ -19,6 +25,7 @@ | @@ -19,6 +25,7 @@ | ||
19 | <td><%= link_to 'Edit', :action => :edit, :id => gamification_plugin_badge.id %></td> | 25 | <td><%= link_to 'Edit', :action => :edit, :id => gamification_plugin_badge.id %></td> |
20 | <td><%= button_without_text :delete, _('Remove'), {:action => :destroy, :id => gamification_plugin_badge.id}, :method => :post, :confirm => _('Are you sure?') %></td> | 26 | <td><%= button_without_text :delete, _('Remove'), {:action => :destroy, :id => gamification_plugin_badge.id}, :method => :post, :confirm => _('Are you sure?') %></td> |
21 | </tr> | 27 | </tr> |
28 | + <% end %> | ||
22 | <% end %> | 29 | <% end %> |
23 | </table> | 30 | </table> |
24 | 31 |
views/gamification_plugin_badges/show.html.erb
@@ -22,6 +22,13 @@ | @@ -22,6 +22,13 @@ | ||
22 | <%= @gamification_plugin_badge.level %> | 22 | <%= @gamification_plugin_badge.level %> |
23 | </p> | 23 | </p> |
24 | 24 | ||
25 | +<% if @gamification_plugin_badge.owner.kind_of?(Organization) %> | ||
26 | +<p> | ||
27 | + <b><%= _('Profile owner:') %></b> | ||
28 | + <%= @gamification_plugin_badge.owner.name %> | ||
29 | + </p> | ||
30 | +<% end %> | ||
31 | + | ||
25 | <p> | 32 | <p> |
26 | <b>Threshold:</b> | 33 | <b>Threshold:</b> |
27 | <% if @gamification_plugin_badge.custom_fields.is_a? Hash %> | 34 | <% if @gamification_plugin_badge.custom_fields.is_a? Hash %> |