mumuki-domain 7.8.1 → 7.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/models/assignment.rb +10 -1
- data/app/models/avatar.rb +7 -1
- data/app/models/concerns/contextualization.rb +1 -0
- data/app/models/concerns/gamified.rb +15 -0
- data/app/models/concerns/with_reminders.rb +1 -1
- data/app/models/concerns/with_target_audience.rb +13 -0
- data/app/models/organization.rb +2 -0
- data/app/models/user.rb +34 -6
- data/app/models/user_stats.rb +16 -0
- data/db/migrate/20200616160640_create_user_stats.rb +10 -0
- data/db/migrate/20200617142217_add_top_submission_status_to_assignments.rb +5 -0
- data/db/migrate/20200717143830_add_target_audience_to_organizations_and_avatars.rb +6 -0
- data/lib/mumuki/domain/extensions.rb +1 -0
- data/lib/mumuki/domain/extensions/time.rb +5 -0
- data/lib/mumuki/domain/factories.rb +2 -1
- data/lib/mumuki/domain/factories/avatar_factory.rb +6 -0
- data/lib/mumuki/domain/factories/user_factory.rb +0 -1
- data/lib/mumuki/domain/helpers/organization.rb +4 -0
- data/lib/mumuki/domain/helpers/user.rb +6 -10
- data/lib/mumuki/domain/incognito.rb +8 -1
- data/lib/mumuki/domain/status/submission/passed.rb +4 -0
- data/lib/mumuki/domain/status/submission/passed_with_warnings.rb +4 -0
- data/lib/mumuki/domain/status/submission/skipped.rb +4 -0
- data/lib/mumuki/domain/status/submission/submission.rb +8 -0
- data/lib/mumuki/domain/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4d324f2eb4b3e06fb42a0aabbbd007c4c828569899c89a789ad681432bb97ba
|
|
4
|
+
data.tar.gz: 3f540fc72a7180e247ee11535316d977920872ecc888c77c7c68346eae0c276e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac7828f09dec30a19e4f4b96bfcfb472fe7fcfc5b53aaeb81e4fb4f5b52533d10b462e9e923d2a2857cec7367cda7d40d6222bd8f8a105dfc84e394b35e552c5
|
|
7
|
+
data.tar.gz: 40cede7e7ff373b1a3a170fbd6bf55bb40faf5c2a814af0849a698f2205a15bff49bca7ba5737577620c48265bad4e42d68e8b4befcb4bbb5d78f9ec82bf23fe
|
data/app/models/assignment.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
class Assignment < Progress
|
|
2
2
|
include Contextualization
|
|
3
3
|
include WithMessages
|
|
4
|
+
include Gamified
|
|
4
5
|
|
|
5
6
|
markdown_on :extra_preview
|
|
6
7
|
|
|
@@ -41,6 +42,7 @@ class Assignment < Progress
|
|
|
41
42
|
alias_method :parent_content, :guide
|
|
42
43
|
alias_method :user, :submitter
|
|
43
44
|
|
|
45
|
+
before_save :award_experience_points!, :update_top_submission!, if: :submission_status_changed?
|
|
44
46
|
after_save :dirty_parent_by_submission!, if: :completion_changed?
|
|
45
47
|
before_validation :set_current_organization!, unless: :organization
|
|
46
48
|
|
|
@@ -161,7 +163,10 @@ class Assignment < Progress
|
|
|
161
163
|
end
|
|
162
164
|
|
|
163
165
|
def to_resource_h
|
|
164
|
-
|
|
166
|
+
excluded_fields = %i(created_at exercise_id id organization_id parent_id solution submission_id
|
|
167
|
+
submission_status submitted_at submitter_id top_submission_status updated_at)
|
|
168
|
+
|
|
169
|
+
as_json(except: excluded_fields,
|
|
165
170
|
include: {
|
|
166
171
|
guide: {
|
|
167
172
|
only: [:slug, :name],
|
|
@@ -224,6 +229,10 @@ class Assignment < Progress
|
|
|
224
229
|
exercise.files_for(current_content)
|
|
225
230
|
end
|
|
226
231
|
|
|
232
|
+
def update_top_submission!
|
|
233
|
+
self.top_submission_status = submission_status unless submission_status.improved_by?(top_submission_status)
|
|
234
|
+
end
|
|
235
|
+
|
|
227
236
|
private
|
|
228
237
|
|
|
229
238
|
def update_submissions_count!
|
data/app/models/avatar.rb
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Gamified
|
|
2
|
+
def award_experience_points!
|
|
3
|
+
points = net_experience
|
|
4
|
+
|
|
5
|
+
if points > 0
|
|
6
|
+
stats = UserStats.stats_for(submitter)
|
|
7
|
+
stats.add_exp!(points)
|
|
8
|
+
stats.save!
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def net_experience
|
|
13
|
+
submission_status.exp_given - top_submission_status.exp_given
|
|
14
|
+
end
|
|
15
|
+
end
|
data/app/models/organization.rb
CHANGED
|
@@ -5,6 +5,8 @@ class Organization < ApplicationRecord
|
|
|
5
5
|
|
|
6
6
|
include Mumukit::Login::OrganizationHelpers
|
|
7
7
|
|
|
8
|
+
include WithTargetAudience
|
|
9
|
+
|
|
8
10
|
serialize :profile, Mumuki::Domain::Organization::Profile
|
|
9
11
|
serialize :settings, Mumuki::Domain::Organization::Settings
|
|
10
12
|
serialize :theme, Mumuki::Domain::Organization::Theme
|
data/app/models/user.rb
CHANGED
|
@@ -30,16 +30,15 @@ class User < ApplicationRecord
|
|
|
30
30
|
|
|
31
31
|
has_many :exams, through: :exam_authorizations
|
|
32
32
|
|
|
33
|
-
after_initialize :init
|
|
34
|
-
|
|
35
33
|
enum gender: %i(female male other unspecified)
|
|
36
|
-
|
|
37
34
|
belongs_to :avatar, optional: true
|
|
38
35
|
|
|
39
36
|
before_validation :set_uid!
|
|
40
37
|
validates :uid, presence: true
|
|
41
38
|
|
|
42
39
|
after_save :welcome_to_new_organizations!, if: :gained_access_to_new_orga?
|
|
40
|
+
after_initialize :init
|
|
41
|
+
PLACEHOLDER_IMAGE_URL = 'user_shape.png'.freeze
|
|
43
42
|
|
|
44
43
|
resource_fields :uid, :social_id, :email, :permissions, :verified_first_name, :verified_last_name, *profile_fields
|
|
45
44
|
|
|
@@ -147,10 +146,14 @@ class User < ApplicationRecord
|
|
|
147
146
|
exams.any? { |e| e.in_progress_for? self }
|
|
148
147
|
end
|
|
149
148
|
|
|
150
|
-
def
|
|
149
|
+
def custom_profile_picture
|
|
151
150
|
avatar&.image_url || image_url
|
|
152
151
|
end
|
|
153
152
|
|
|
153
|
+
def profile_picture
|
|
154
|
+
custom_profile_picture || placeholder_image_url
|
|
155
|
+
end
|
|
156
|
+
|
|
154
157
|
def bury!
|
|
155
158
|
# TODO change avatar
|
|
156
159
|
update! self.class.buried_profile.merge(accepts_reminders: false, gender: nil, birthdate: nil)
|
|
@@ -215,11 +218,25 @@ class User < ApplicationRecord
|
|
|
215
218
|
false
|
|
216
219
|
end
|
|
217
220
|
|
|
221
|
+
def current_audience
|
|
222
|
+
current_organic_context&.target_audience
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def placeholder_image_url
|
|
226
|
+
PLACEHOLDER_IMAGE_URL
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def age
|
|
230
|
+
if birthdate.present?
|
|
231
|
+
@age ||= Time.now.round_years_since(birthdate.to_time)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
218
235
|
private
|
|
219
236
|
|
|
220
237
|
def welcome_to_new_organizations!
|
|
221
238
|
new_accessible_organizations.each do |organization|
|
|
222
|
-
UserMailer.welcome_email(self, organization).
|
|
239
|
+
UserMailer.welcome_email(self, organization).deliver_now rescue nil if organization.greet_new_users?
|
|
223
240
|
end
|
|
224
241
|
end
|
|
225
242
|
|
|
@@ -240,7 +257,10 @@ class User < ApplicationRecord
|
|
|
240
257
|
end
|
|
241
258
|
|
|
242
259
|
def init
|
|
243
|
-
|
|
260
|
+
if custom_profile_picture.blank?
|
|
261
|
+
self.avatar = Avatar.sample_for(self)
|
|
262
|
+
save if persisted?
|
|
263
|
+
end
|
|
244
264
|
end
|
|
245
265
|
|
|
246
266
|
def self.sync_key_id_field
|
|
@@ -265,4 +285,12 @@ class User < ApplicationRecord
|
|
|
265
285
|
def self.buried_profile
|
|
266
286
|
(@buried_profile || {}).slice(:first_name, :last_name, :email)
|
|
267
287
|
end
|
|
288
|
+
|
|
289
|
+
def current_organic_context
|
|
290
|
+
if Organization.current?
|
|
291
|
+
Organization.current
|
|
292
|
+
else
|
|
293
|
+
main_organization
|
|
294
|
+
end
|
|
295
|
+
end
|
|
268
296
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class UserStats < ApplicationRecord
|
|
2
|
+
belongs_to :organization
|
|
3
|
+
belongs_to :user
|
|
4
|
+
|
|
5
|
+
def self.stats_for(user)
|
|
6
|
+
UserStats.find_or_initialize_by(user: user, organization: Organization.current)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.exp_for(user)
|
|
10
|
+
self.stats_for(user).exp
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_exp!(points)
|
|
14
|
+
self.exp += points
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative './factories/api_client_factory'
|
|
2
2
|
require_relative './factories/assignments_factory'
|
|
3
|
+
require_relative './factories/avatar_factory'
|
|
3
4
|
require_relative './factories/book_factory'
|
|
4
5
|
require_relative './factories/chapter_factory'
|
|
5
6
|
require_relative './factories/complement_factory'
|
|
@@ -15,4 +16,4 @@ require_relative './factories/message_factory'
|
|
|
15
16
|
require_relative './factories/organization_factory'
|
|
16
17
|
require_relative './factories/topic_factory'
|
|
17
18
|
require_relative './factories/user_factory'
|
|
18
|
-
require_relative './factories/usage_factory'
|
|
19
|
+
require_relative './factories/usage_factory'
|
|
@@ -13,6 +13,8 @@ module Mumuki::Domain::Helpers::User
|
|
|
13
13
|
:protect!,
|
|
14
14
|
:protect_delegation!,
|
|
15
15
|
:protect_permissions_assignment!,
|
|
16
|
+
:student_granted_organizations,
|
|
17
|
+
:any_granted_organizations,
|
|
16
18
|
to: :permissions
|
|
17
19
|
|
|
18
20
|
def platform_class_name
|
|
@@ -71,12 +73,10 @@ module Mumuki::Domain::Helpers::User
|
|
|
71
73
|
"#{full_name} <#{email}> [#{uid}]"
|
|
72
74
|
end
|
|
73
75
|
|
|
74
|
-
##
|
|
76
|
+
## Accessible organizations
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Mumukit::Platform::Organization.find_by_name!(org) rescue nil
|
|
79
|
-
end.compact
|
|
78
|
+
revamp_accessor :any_granted_organizations, :student_granted_organizations do |_, _, result|
|
|
79
|
+
result.map { |org| Mumukit::Platform::Organization.find_by_name!(org) rescue nil }.compact
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def has_student_granted_organizations?
|
|
@@ -84,11 +84,7 @@ module Mumuki::Domain::Helpers::User
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def main_organization
|
|
87
|
-
student_granted_organizations.first
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def has_main_organization?
|
|
91
|
-
student_granted_organizations.length == 1
|
|
87
|
+
student_granted_organizations.first || any_granted_organizations.first
|
|
92
88
|
end
|
|
93
89
|
|
|
94
90
|
def has_immersive_main_organization?
|
|
@@ -40,6 +40,10 @@ module Mumuki::Domain
|
|
|
40
40
|
false
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def can_discuss_in?(*)
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
43
47
|
# ========
|
|
44
48
|
# Visiting
|
|
45
49
|
# ========
|
|
@@ -88,6 +92,10 @@ module Mumuki::Domain
|
|
|
88
92
|
raise "unknown attribute #{key}"
|
|
89
93
|
end
|
|
90
94
|
|
|
95
|
+
def new_record?
|
|
96
|
+
false
|
|
97
|
+
end
|
|
98
|
+
|
|
91
99
|
def self.primary_key
|
|
92
100
|
'id'
|
|
93
101
|
end
|
|
@@ -105,7 +113,6 @@ module Mumuki::Domain
|
|
|
105
113
|
assignment.assign_attributes results
|
|
106
114
|
results
|
|
107
115
|
end
|
|
108
|
-
|
|
109
116
|
end
|
|
110
117
|
|
|
111
118
|
Incognito = IncognitoClass.new
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mumuki-domain
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.
|
|
4
|
+
version: 7.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Franco Leonardo Bulgarelli
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-09-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -256,6 +256,7 @@ files:
|
|
|
256
256
|
- app/models/concerns/contextualization.rb
|
|
257
257
|
- app/models/concerns/disabling.rb
|
|
258
258
|
- app/models/concerns/friendly_name.rb
|
|
259
|
+
- app/models/concerns/gamified.rb
|
|
259
260
|
- app/models/concerns/guide_container.rb
|
|
260
261
|
- app/models/concerns/navigation/parent_navigation.rb
|
|
261
262
|
- app/models/concerns/navigation/siblings_navigation.rb
|
|
@@ -292,6 +293,7 @@ files:
|
|
|
292
293
|
- app/models/concerns/with_scoped_queries/page.rb
|
|
293
294
|
- app/models/concerns/with_scoped_queries/sort.rb
|
|
294
295
|
- app/models/concerns/with_slug.rb
|
|
296
|
+
- app/models/concerns/with_target_audience.rb
|
|
295
297
|
- app/models/concerns/with_usages.rb
|
|
296
298
|
- app/models/concerns/with_user_navigation.rb
|
|
297
299
|
- app/models/content.rb
|
|
@@ -322,6 +324,7 @@ files:
|
|
|
322
324
|
- app/models/upvote.rb
|
|
323
325
|
- app/models/usage.rb
|
|
324
326
|
- app/models/user.rb
|
|
327
|
+
- app/models/user_stats.rb
|
|
325
328
|
- app/models/with_stats.rb
|
|
326
329
|
- db/migrate/20141120231135_create_exercises.rb
|
|
327
330
|
- db/migrate/20141120231735_create_submissions.rb
|
|
@@ -608,7 +611,10 @@ files:
|
|
|
608
611
|
- db/migrate/20200601203033_add_course_to_exam.rb
|
|
609
612
|
- db/migrate/20200605161350_add_passing_criterions_to_exam.rb
|
|
610
613
|
- db/migrate/20200608132959_add_progressive_display_lookahead_to_organizations.rb
|
|
614
|
+
- db/migrate/20200616160640_create_user_stats.rb
|
|
615
|
+
- db/migrate/20200617142217_add_top_submission_status_to_assignments.rb
|
|
611
616
|
- db/migrate/20200702165503_add_messages_count_to_discussion.rb
|
|
617
|
+
- db/migrate/20200717143830_add_target_audience_to_organizations_and_avatars.rb
|
|
612
618
|
- db/migrate/20200728162727_add_not_actually_a_question_field_to_messages.rb
|
|
613
619
|
- db/migrate/20200728163038_add_requires_moderator_response_to_discussions.rb
|
|
614
620
|
- db/migrate/20200730221001_add_trusted_for_forum_to_user.rb
|
|
@@ -634,9 +640,11 @@ files:
|
|
|
634
640
|
- lib/mumuki/domain/extensions/hash.rb
|
|
635
641
|
- lib/mumuki/domain/extensions/module.rb
|
|
636
642
|
- lib/mumuki/domain/extensions/string.rb
|
|
643
|
+
- lib/mumuki/domain/extensions/time.rb
|
|
637
644
|
- lib/mumuki/domain/factories.rb
|
|
638
645
|
- lib/mumuki/domain/factories/api_client_factory.rb
|
|
639
646
|
- lib/mumuki/domain/factories/assignments_factory.rb
|
|
647
|
+
- lib/mumuki/domain/factories/avatar_factory.rb
|
|
640
648
|
- lib/mumuki/domain/factories/book_factory.rb
|
|
641
649
|
- lib/mumuki/domain/factories/chapter_factory.rb
|
|
642
650
|
- lib/mumuki/domain/factories/complement_factory.rb
|