mumuki-classroom 8.5.0 → 8.6.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/lib/mumuki/classroom/event.rb +1 -0
- data/lib/mumuki/classroom/event/progress_transfer.rb +31 -0
- data/lib/mumuki/classroom/event/progress_transfer/base.rb +111 -0
- data/lib/mumuki/classroom/event/progress_transfer/copy.rb +9 -0
- data/lib/mumuki/classroom/event/progress_transfer/move.rb +9 -0
- data/lib/mumuki/classroom/models/assignment.rb +4 -1
- data/lib/mumuki/classroom/models/concerns/with_submission_process.rb +3 -20
- data/lib/mumuki/classroom/models/failed_submission.rb +4 -1
- data/lib/mumuki/classroom/models/guide_progress.rb +4 -0
- data/lib/mumuki/classroom/models/student.rb +18 -2
- data/lib/mumuki/classroom/version.rb +1 -1
- data/lib/tasks/mumuki/progress_transfers.rake +17 -0
- metadata +9 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b9478687b7b21f32f26aacddb48094ab88ac960c625ae104321a913fd980083f
|
|
4
|
+
data.tar.gz: d140d89d369715662e25dfddb1338a823e378402e26c9e491f167897c5ad65b7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 24e65c6cf9f54f4a3a0b826221ff5979d329c790390f9fe950a684d1606c9bb78943ba3e6e6d4dd9937f1341e2dbcd16b34b8040b6ea4c63f15fffa521d45c23
|
|
7
|
+
data.tar.gz: d50f24e931da4ce4986fc7736c38653fe36bc0db32f447c974f4e16a7b43bde545f853ed8797572d0784921f1cdf398ccd33ae2379fa26a553912e0ad63308ad
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Mumuki::Classroom::Event::ProgressTransfer
|
|
2
|
+
attr_reader :body
|
|
3
|
+
|
|
4
|
+
def initialize(body)
|
|
5
|
+
@body = body
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def execute!
|
|
9
|
+
transfer_type.new(progress_item, source_organization, destination_organization).execute!
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def source_organization
|
|
13
|
+
Organization.locate! body[:from]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def destination_organization
|
|
17
|
+
Organization.locate! body[:to]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def progress_item
|
|
21
|
+
Indicator.find(body[:item_id])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def transfer_type
|
|
25
|
+
self.class.const_get(body[:transfer_type].camelize)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
require_relative 'progress_transfer/base'
|
|
30
|
+
require_relative 'progress_transfer/copy'
|
|
31
|
+
require_relative 'progress_transfer/move'
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
class Mumuki::Classroom::Event::ProgressTransfer::Base
|
|
2
|
+
attr_reader :indicator, :source_organization
|
|
3
|
+
|
|
4
|
+
def initialize(indicator, source_organization, destination_organization)
|
|
5
|
+
@indicator = indicator
|
|
6
|
+
@source_organization = source_organization
|
|
7
|
+
@destination_organization = destination_organization
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def execute!
|
|
11
|
+
raise ActiveRecord::RecordNotFound, "Mumuki::Classroom::Student not found" unless old_student && new_student
|
|
12
|
+
|
|
13
|
+
new_student.destroy_progress_for_guide!(indicator.content)
|
|
14
|
+
destination_organization.switch!
|
|
15
|
+
|
|
16
|
+
indicator.assignments.each do |assignment|
|
|
17
|
+
transfer_sibling_for(assignment)&.update! organization: destination_organization.name,
|
|
18
|
+
course: new_course,
|
|
19
|
+
guide: guide_h
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
transfer_guide_progress!
|
|
23
|
+
update_student!(old_student)
|
|
24
|
+
update_student!(new_student)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def update_student!(student)
|
|
30
|
+
student.update_all_stats
|
|
31
|
+
student.update_last_assignment_for
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def destination_organization
|
|
35
|
+
@destination_organization
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def transfer_guide_progress!
|
|
39
|
+
transfer_item.update!(guide: guide_h,
|
|
40
|
+
student: new_student.dup,
|
|
41
|
+
organization: destination_organization.name,
|
|
42
|
+
course: new_course)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def guide_progress
|
|
46
|
+
Mumuki::Classroom::GuideProgress.find_by(guide_progress_query)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def classroom_sibling_for(assignment)
|
|
50
|
+
Mumuki::Classroom::Assignment.classroom_sibling_for(assignment, source_organization.name)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def new_student
|
|
54
|
+
@new_student ||= student_for destination_organization.name
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def old_student
|
|
58
|
+
@old_student ||= student_for source_organization
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def student_for(organization)
|
|
62
|
+
Mumuki::Classroom::Student.last_updated_student_by organization: organization, uid: user.uid
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def new_course
|
|
66
|
+
new_student.course
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def old_course
|
|
70
|
+
old_student.course
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def guide_progress_query
|
|
74
|
+
{
|
|
75
|
+
organization: source_organization,
|
|
76
|
+
course: old_course,
|
|
77
|
+
'guide.slug': guide.slug,
|
|
78
|
+
'student.uid': user.uid
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def user
|
|
83
|
+
indicator.user
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def guide
|
|
87
|
+
indicator.content
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def guide_parent
|
|
91
|
+
guide.usage_in_organization
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def guide_h
|
|
95
|
+
@guide_h ||= guide.as_json(
|
|
96
|
+
only: [:slug, :name],
|
|
97
|
+
include: {
|
|
98
|
+
language: {
|
|
99
|
+
only: [:name, :devicon]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
).merge(
|
|
103
|
+
parent: {
|
|
104
|
+
type: guide_parent.class.to_s,
|
|
105
|
+
name: guide.name,
|
|
106
|
+
position: guide_parent.number,
|
|
107
|
+
chapter: guide.chapter.as_json(only: [:id], methods: [:name])
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -143,6 +143,9 @@ class Mumuki::Classroom::Assignment < Mumuki::Classroom::Document
|
|
|
143
143
|
stats[:failed] += stats.delete(:errored) || 0
|
|
144
144
|
stats.slice(*empty_stats.keys)
|
|
145
145
|
end
|
|
146
|
-
end
|
|
147
146
|
|
|
147
|
+
def classroom_sibling_for(assignment, organization)
|
|
148
|
+
find_by(organization: organization, 'student.uid': assignment.user.uid, 'exercise.eid': assignment.exercise.bibliotheca_id)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
148
151
|
end
|
|
@@ -22,7 +22,7 @@ module WithSubmissionProcess
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def find_student_from(json)
|
|
25
|
-
Mumuki::Classroom::Student.find_by(organization: organization(json), course: course_slug(json), uid: uid(json))
|
|
25
|
+
Mumuki::Classroom::Student.find_by(organization: organization(json), course: course_slug(json), uid: uid(json))
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def update_student_progress(json)
|
|
@@ -99,15 +99,7 @@ module WithSubmissionProcess
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def student_from(json)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
{uid: student[:uid],
|
|
105
|
-
name: student[:name],
|
|
106
|
-
email: student[:email],
|
|
107
|
-
image_url: student[:image_url],
|
|
108
|
-
social_id: student[:social_id],
|
|
109
|
-
last_name: student[:last_name],
|
|
110
|
-
first_name: student[:first_name]}.compact
|
|
102
|
+
json[:student].as_submission_json
|
|
111
103
|
end
|
|
112
104
|
|
|
113
105
|
def guide_from(json)
|
|
@@ -134,15 +126,6 @@ module WithSubmissionProcess
|
|
|
134
126
|
end
|
|
135
127
|
|
|
136
128
|
def submission_from(json)
|
|
137
|
-
|
|
138
|
-
status: json[:status],
|
|
139
|
-
result: json[:result],
|
|
140
|
-
content: json[:content],
|
|
141
|
-
feedback: json[:feedback],
|
|
142
|
-
created_at: json[:created_at],
|
|
143
|
-
test_results: json[:test_results],
|
|
144
|
-
submissions_count: json[:submissions_count],
|
|
145
|
-
expectation_results: json[:expectation_results],
|
|
146
|
-
origin_ip: json[:origin_ip]}.compact
|
|
129
|
+
Mumuki::Classroom::FailedSubmission.new(json).as_assignment_submission
|
|
147
130
|
end
|
|
148
131
|
end
|
|
@@ -4,7 +4,7 @@ class Mumuki::Classroom::FailedSubmission < Mumuki::Classroom::Document
|
|
|
4
4
|
|
|
5
5
|
include Mongoid::Attributes::Dynamic
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
include Mongoid::Timestamps::Created
|
|
8
8
|
|
|
9
9
|
create_index 'organization': 1, 'submitter.uid': 1
|
|
10
10
|
create_index({'guide.slug': 1, 'exercise.eid': 1}, {name: 'ExBibIdIndex'})
|
|
@@ -13,4 +13,7 @@ class Mumuki::Classroom::FailedSubmission < Mumuki::Classroom::Document
|
|
|
13
13
|
scope :find_by_uid, -> (uid) { where 'submitter.uid': uid }
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
def as_assignment_submission
|
|
17
|
+
as_json(only: %i(sid status result content feedback created_at test_results submissions_count expectation_results origin_ip)).compact
|
|
18
|
+
end
|
|
16
19
|
end
|
|
@@ -52,6 +52,10 @@ class Mumuki::Classroom::GuideProgress < Mumuki::Classroom::Document
|
|
|
52
52
|
def uid_field
|
|
53
53
|
'student.uid'.to_sym
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
def progresses_for(progress_item, student)
|
|
57
|
+
where(organization: progress_item.organization, course: student.course, slug: progress_item.content.slug, 'student.uid': student.uid)
|
|
58
|
+
end
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
end
|
|
@@ -16,11 +16,23 @@ class Mumuki::Classroom::Student < Mumuki::Classroom::Document
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def destroy_cascade!
|
|
19
|
-
|
|
20
|
-
Mumuki::Classroom::Assignment.destroy_all_by!(sub_student_query uid)
|
|
19
|
+
destroy_progress!
|
|
21
20
|
destroy!
|
|
22
21
|
end
|
|
23
22
|
|
|
23
|
+
def destroy_progress!
|
|
24
|
+
destroy_progress_for_query!(sub_student_query uid)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def destroy_progress_for_guide!(guide)
|
|
28
|
+
destroy_progress_for_query!(sub_student_query(uid).merge 'guide.slug': guide.slug)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def destroy_progress_for_query!(query)
|
|
32
|
+
Mumuki::Classroom::GuideProgress.destroy_all_by!(query)
|
|
33
|
+
Mumuki::Classroom::Assignment.destroy_all_by!(query)
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
def update_all_stats
|
|
25
37
|
all_stats = Mumuki::Classroom::Assignment.stats_by(sub_student_query uid)
|
|
26
38
|
update_attributes!(stats: all_stats)
|
|
@@ -52,6 +64,10 @@ class Mumuki::Classroom::Student < Mumuki::Classroom::Document
|
|
|
52
64
|
update_attributes!(last_assignment: Mumuki::Classroom::GuideProgress.last_assignment_by(sub_student_query uid))
|
|
53
65
|
end
|
|
54
66
|
|
|
67
|
+
def as_submission_json
|
|
68
|
+
as_json(only: %i(uid name email image_url social_id last_name first_name)).compact
|
|
69
|
+
end
|
|
70
|
+
|
|
55
71
|
class << self
|
|
56
72
|
def report(criteria, &block)
|
|
57
73
|
where(criteria).select(&block).as_json(only: [:first_name, :last_name, :email, :created_at, :detached_at])
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
namespace :classroom do
|
|
2
|
+
namespace :progress_transfers do
|
|
3
|
+
task listen: :environment do
|
|
4
|
+
Mumukit::Nuntius::Logger.info 'Listening to student progress-transfers'
|
|
5
|
+
|
|
6
|
+
Mumukit::Nuntius::Consumer.negligent_start! 'progress-transfers' do |body|
|
|
7
|
+
begin
|
|
8
|
+
Mumuki::Classroom::Event::ProgressTransfer.new(body).execute!
|
|
9
|
+
|
|
10
|
+
Mumukit::Nuntius::Logger.info "Processing progress transfer #{body[:item_id]}"
|
|
11
|
+
rescue => e
|
|
12
|
+
Mumukit::Nuntius::Logger.warn "Mumuki::Classroom::ProgressTransfer failed #{e}. body was: #{body}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mumuki-classroom
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Franco Bulgarelli
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-02-
|
|
11
|
+
date: 2021-02-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: 8.
|
|
89
|
+
version: 8.6.0
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: 8.
|
|
96
|
+
version: 8.6.0
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: mumukit-login
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -226,6 +226,10 @@ files:
|
|
|
226
226
|
- lib/mumuki/classroom/collection.rb
|
|
227
227
|
- lib/mumuki/classroom/engine.rb
|
|
228
228
|
- lib/mumuki/classroom/event.rb
|
|
229
|
+
- lib/mumuki/classroom/event/progress_transfer.rb
|
|
230
|
+
- lib/mumuki/classroom/event/progress_transfer/base.rb
|
|
231
|
+
- lib/mumuki/classroom/event/progress_transfer/copy.rb
|
|
232
|
+
- lib/mumuki/classroom/event/progress_transfer/move.rb
|
|
229
233
|
- lib/mumuki/classroom/event/user_changed.rb
|
|
230
234
|
- lib/mumuki/classroom/locales/en.yml
|
|
231
235
|
- lib/mumuki/classroom/locales/es-CL.yml
|
|
@@ -281,6 +285,7 @@ files:
|
|
|
281
285
|
- lib/mumuki/profile.rb
|
|
282
286
|
- lib/mumuki/views/threads.html.erb
|
|
283
287
|
- lib/tasks/mumuki/messages.rake
|
|
288
|
+
- lib/tasks/mumuki/progress_transfers.rake
|
|
284
289
|
- lib/tasks/mumuki/resubmissions.rake
|
|
285
290
|
- lib/tasks/mumuki/students.rake
|
|
286
291
|
- lib/tasks/mumuki/submissions.rake
|