-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexport_lom.rb
236 lines (221 loc) · 6.19 KB
/
export_lom.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# frozen_string_literal: true
module LomService
# rubocop:disable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
class ExportLom < ServiceBase
include Rails.application.routes.url_helpers
def initialize(task:, xml:)
super()
@task = task
@xml = xml
end
def execute
@xml.lom(xmlns: 'http://ltsc.ieee.org/xsd/LOM') do
oml_general(@xml)
oml_lifecycle(@xml)
oml_meta_metadata(@xml)
oml_technical(@xml)
oml_educational(@xml)
oml_rights(@xml)
oml_relation(@xml)
oml_annotation(@xml)
# Other top-level elements: classification.
end
end
private
def oml_general(xml)
xml.general do
xml.identifier do
xml.catalog 'UUID'
xml.entry @task.uuid
end
xml.title do
xml.string @task.title, language: @task.iso639_lang
end
xml.language @task.iso639_lang
xml.description do
html_fragment = Loofah.fragment(ApplicationController.helpers.render_markdown(@task.description))
html_fragment.scrub!(NbpScrubber.new)
xml.string html_fragment.to_s, language: @task.iso639_lang
end
if @task.programming_language&.language.present?
xml.keyword do
xml.string "programming language: #{@task.programming_language.language}", language: 'en'
end
if @task.programming_language&.version.present?
xml.keyword do
xml.string "programming language version: #{@task.programming_language.version}", language: 'en'
end
end
end
if @task.ratings.any?
xml.keyword do
xml.string "average rating: #{@task.rating_star}/5.0", language: 'en'
end
end
@task.labels.each do |label|
xml.keyword do
xml.string label.name, language: 'en'
end
end
xml.structure do
xml.value 'atomic'
end
xml.aggregationLevel do
xml.value 1
end
end
end
def oml_lifecycle(xml)
xml.lifeCycle do
xml.version do
xml.string task_version, language: 'en'
end
xml.status do
xml.value 'final'
end
xml.contribute do
xml.role do
xml.value 'author'
end
xml.entity vcard(@task.user)
xml.date do
# We omit the time part, since the regex provided by the xsd schema is broken regarding the time zone part.
xml.dateTime @task.updated_at.to_date.iso8601
end
end
end
end
def oml_meta_metadata(xml)
xml.metaMetadata do
xml.identifier do
xml.catalog 'URI'
xml.entry bridges_lom_task_url(@task)
end
xml.metadataSchema 'ProFormA MD 1.0'
xml.language 'en'
end
end
def oml_technical(xml)
xml.technical do
xml.format 'text/xml'
xml.location task_url(@task, default_url_options)
xml.location download_task_url(@task, default_url_options)
end
end
def oml_educational(xml)
xml.educational do
xml.interactivityType do
xml.value 'active'
end
xml.learningResourceType do
xml.value 'exercise'
end
xml.interactivityLevel do
xml.value 'high'
end
xml.semanticDensity do
xml.value 'high'
end
xml.intendedEndUserRole do
xml.value 'learner'
end
xml.context_ do
xml.value 'school'
end
xml.context_ do
xml.value 'higher education'
end
xml.context_ do
xml.value 'training'
end
xml.typicalAgeRange do
xml.string '13-'
end
xml.description do
xml.string @task.internal_description, language: @task.iso639_lang
end
xml.language @task.iso639_lang
end
end
def oml_rights(xml)
xml.rights do
xml.cost do
xml.value 'no'
end
xml.copyrightAndOtherRestrictions do
xml.value 'yes'
end
if @task.license.present?
xml.description do
xml.string @task.license.to_s, language: 'en'
end
else
xml.description do
xml.string 'Unknown license', language: 'en'
end
end
end
end
def oml_relation(xml)
parent = Task.find_by(uuid: @task.parent_uuid)
if parent.present?
xml.relation do
xml.kind do
xml.source 'LOMv1.0'
xml.value 'isversionof'
end
xml.resource do
xml.identifier do
xml.catalog 'UUID'
xml.entry parent.uuid
end
xml.identifier do
xml.catalog 'URI'
xml.entry task_url(parent, default_url_options)
end
xml.description do
xml.string parent.description, language: parent.iso639_lang
end
end
end
end
end
def oml_annotation(xml)
@task.comments.each do |comment|
xml.annotation do
xml.entity vcard(comment.user)
xml.date do
# We omit the time part, since the regex provided by the xsd schema is broken regarding the time zone part.
xml.dateTime comment.updated_at.to_date.iso8601
end
xml.description do
xml.string comment.text, language: @task.iso639_lang
end
end
end
end
def task_version
# TODO: Fix this N+1 query for example by adding a version column for tasks
version = 1
ancestor = @task
while ancestor.parent_uuid.present?
ancestor = Task.find_by(uuid: ancestor.parent_uuid)
version += 1
end
version
end
def vcard(user)
<<~VCARD
BEGIN:VCARD
VERSION:3.0
FN;CHARSET=UTF-8:#{user.name}
N;CHARSET=UTF-8:#{user.last_name};#{user.first_name};;;
END:VCARD
VCARD
end
def default_url_options
::Rails.application.config.action_mailer.default_url_options
end
# rubocop:enable all
end
end