asker-tool 2.1.6 → 2.2.2
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/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +14 -15
- data/bin/asker +1 -1
- data/lib/asker/ai/ai.rb +6 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/concept_ai.rb +12 -3
- data/lib/asker/ai/question.rb +28 -6
- data/lib/asker/ai/stages/base_stage.rb +45 -6
- data/lib/asker/ai/stages/stage_b.rb +90 -49
- data/lib/asker/ai/stages/stage_d.rb +69 -90
- data/lib/asker/ai/stages/stage_f.rb +47 -38
- data/lib/asker/ai/stages/stage_i.rb +79 -92
- data/lib/asker/ai/stages/stage_s.rb +41 -36
- data/lib/asker/ai/stages/stage_t.rb +114 -73
- data/lib/asker/application.rb +7 -15
- data/lib/asker/check_input/input_data.rb +358 -0
- data/lib/asker/check_input.rb +51 -0
- data/lib/asker/cli.rb +28 -28
- data/lib/asker/data/code.rb +5 -16
- data/lib/asker/data/concept.rb +71 -24
- data/lib/asker/data/project_data.rb +63 -0
- data/lib/asker/data/table.rb +2 -0
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +8 -16
- data/lib/asker/displayer/code_displayer.rb +7 -0
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +24 -22
- data/lib/asker/displayer/concept_displayer.rb +9 -4
- data/lib/asker/displayer/stats_displayer.rb +8 -0
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +16 -10
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
- data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +9 -6
- data/lib/asker/files/{config.ini → asker.ini} +14 -4
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/files/language/du/mistakes.yaml +82 -0
- data/lib/asker/files/language/du/templates.yaml +28 -49
- data/lib/asker/files/language/en/templates.yaml +19 -19
- data/lib/asker/files/language/es/mistakes.yaml +9 -7
- data/lib/asker/files/language/es/templates.yaml +19 -19
- data/lib/asker/files/language/fr/connectors.yaml +68 -84
- data/lib/asker/files/language/fr/templates.yaml +22 -22
- data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
- data/lib/asker/formatter/concept_string_formatter.rb +7 -4
- data/lib/asker/formatter/moodle/matching.erb +38 -0
- data/lib/asker/formatter/moodle/multichoice.erb +49 -0
- data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
- data/lib/asker/formatter/moodle/truefalse.erb +47 -0
- data/lib/asker/formatter/question_gift_formatter.rb +30 -20
- data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
- data/lib/asker/lang/lang_factory.rb +7 -1
- data/lib/asker/loader/code_loader.rb +1 -1
- data/lib/asker/loader/content_loader.rb +12 -14
- data/lib/asker/loader/directory_loader.rb +1 -8
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +1 -3
- data/lib/asker/loader/image_url_loader.rb +8 -9
- data/lib/asker/loader/input_loader.rb +5 -6
- data/lib/asker/loader/project_loader.rb +18 -10
- data/lib/asker/logger.rb +35 -8
- data/lib/asker/skeleton.rb +3 -2
- data/lib/asker.rb +72 -43
- metadata +43 -17
- data/lib/asker/checker.rb +0 -455
- data/lib/asker/project.rb +0 -146
@@ -1,160 +1,139 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
require_relative 'base_stage'
|
6
6
|
require_relative '../question'
|
7
7
|
|
8
|
+
# range d1-d4
|
8
9
|
class StageD < BaseStage
|
9
|
-
# range d1-d4
|
10
|
-
|
11
10
|
def run
|
12
11
|
# Stage D: process every definition, I mean every <def> tag
|
13
12
|
questions = []
|
14
|
-
return questions unless type == 'text'
|
13
|
+
return questions unless concept.type == 'text'
|
15
14
|
|
15
|
+
lang = concept.lang
|
16
16
|
# for every <text> do this
|
17
|
-
texts.each do |t|
|
18
|
-
s=Set.new [name(:raw), lang.text_for(:none)]
|
19
|
-
neighbors.each { |n| s.add n[:concept].name(:decorated) }
|
20
|
-
a=s.to_a
|
17
|
+
concept.texts.each do |t|
|
18
|
+
s = Set.new [name(:raw), lang.text_for(:none)]
|
19
|
+
concept.neighbors.each { |n| s.add n[:concept].name(:decorated) }
|
20
|
+
a = s.to_a
|
21
21
|
|
22
22
|
# Question choose between 4 options
|
23
23
|
if s.count > 3
|
24
|
-
q=Question.new(:choice)
|
25
|
-
q.name="#{name(:id)}-#{num}-d1choose"
|
26
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
|
27
|
-
q.good=name(:raw)
|
24
|
+
q = Question.new(:choice)
|
25
|
+
q.name = "#{name(:id)}-#{num}-d1choose"
|
26
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
27
|
+
q.good = name(:raw)
|
28
28
|
q.bads << lang.text_for(:none)
|
29
29
|
q.bads << a[2]
|
30
30
|
q.bads << a[3]
|
31
31
|
questions << q
|
32
32
|
end
|
33
33
|
|
34
|
-
#Question choose between 4 options, good none (Syntax error)
|
35
|
-
if s.count>3
|
36
|
-
q=Question.new(:choice)
|
37
|
-
q.name="#{name(:id)}-#{num}-d1none-misspelled"
|
38
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
|
34
|
+
# Question choose between 4 options, good none (Syntax error)
|
35
|
+
if s.count > 3
|
36
|
+
q = Question.new(:choice)
|
37
|
+
q.name = "#{name(:id)}-#{num}-d1none-misspelled"
|
38
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
39
39
|
q.good = lang.text_for(:none)
|
40
40
|
q.bads << lang.do_mistake_to(name(:raw))
|
41
41
|
q.bads << a[2]
|
42
42
|
q.bads << a[3]
|
43
|
-
q.feedback="Option misspelled!: #{name(:raw)}"
|
43
|
+
q.feedback = "Option misspelled!: #{name(:raw)}"
|
44
44
|
questions << q
|
45
45
|
end
|
46
46
|
|
47
47
|
s.delete(name(:raw))
|
48
|
-
a=s.to_a
|
48
|
+
a = s.to_a
|
49
49
|
|
50
|
-
#Question choose between 4 options, good none
|
51
|
-
if s.count>3
|
50
|
+
# Question choose between 4 options, good none
|
51
|
+
if s.count > 3
|
52
52
|
q = Question.new(:choice)
|
53
|
-
q.name="#{name(:id)}-#{num}-d1none"
|
54
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
|
55
|
-
q.good=lang.text_for(:none)
|
53
|
+
q.name = "#{name(:id)}-#{num}-d1none"
|
54
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
55
|
+
q.good = lang.text_for(:none)
|
56
56
|
q.bads << a[1]
|
57
57
|
q.bads << a[2]
|
58
58
|
q.bads << a[3]
|
59
59
|
questions << q
|
60
60
|
end
|
61
61
|
|
62
|
-
#Question
|
63
|
-
#q = Question.new(:boolean)
|
64
|
-
#q.name="#{name}-#{num}-d2true"
|
65
|
-
#q.text=random_image_for(name) + lang.text_for(:d2,name,t)
|
66
|
-
#q.good="TRUE"
|
67
|
-
#questions << q
|
68
|
-
|
62
|
+
# Question choice => mispelled
|
69
63
|
q = Question.new(:choice)
|
70
|
-
q.name="#{name(:id)}-#{num}-d2def-
|
71
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d2,name(:decorated), lang.do_mistake_to(t)
|
72
|
-
q.good=lang.text_for(:misspelling)
|
64
|
+
q.name = "#{name(:id)}-#{num}-d2def-misspelled"
|
65
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, name(:decorated), lang.do_mistake_to(t))
|
66
|
+
q.good = lang.text_for(:misspelling)
|
73
67
|
q.bads << lang.text_for(:true)
|
74
68
|
q.bads << lang.text_for(:false)
|
75
|
-
q.feedback="Definition text
|
69
|
+
q.feedback = "Definition text misspelled!: #{t}"
|
76
70
|
questions << q
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
72
|
+
# Question choice => name mispelled
|
73
|
+
q = Question.new(:choice)
|
74
|
+
q.name = "#{name(:id)}-#{num}-d2name-misspelled"
|
75
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, lang.do_mistake_to(name(:raw)), t)
|
76
|
+
q.good = lang.text_for(:misspelling)
|
77
|
+
q.bads << lang.text_for(:true)
|
78
|
+
q.bads << lang.text_for(:false)
|
79
|
+
q.feedback = "Concept name misspelled!: #{name(:raw)}"
|
80
|
+
questions << q
|
88
81
|
|
82
|
+
# Question choice => true
|
89
83
|
q = Question.new(:choice)
|
90
|
-
q.name="#{name(:id)}-#{num}-d2true"
|
91
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d2, name(:raw), t
|
84
|
+
q.name = "#{name(:id)}-#{num}-d2true"
|
85
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, name(:raw), t)
|
92
86
|
q.good = lang.text_for(:true)
|
93
87
|
q.bads << lang.text_for(:misspelling)
|
94
88
|
q.bads << lang.text_for(:false)
|
95
89
|
questions << q
|
96
90
|
|
97
|
-
|
91
|
+
# Question choice => false
|
92
|
+
if a.size > 1
|
98
93
|
q = Question.new(:choice)
|
99
|
-
q.name="#{name(:id)}-#{num}-d2false-misspelled"
|
100
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d2, a[1], t)
|
94
|
+
q.name = "#{name(:id)}-#{num}-d2false-misspelled"
|
95
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, a[1], t)
|
101
96
|
q.good = lang.text_for(:false)
|
102
97
|
q.bads << lang.text_for(:misspelling)
|
103
98
|
q.bads << lang.text_for(:true)
|
104
99
|
questions << q
|
105
100
|
end
|
106
101
|
|
107
|
-
#Question
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
if type=="text"
|
117
|
-
#Question hidden name questions
|
118
|
-
q = Question.new(:short)
|
119
|
-
q.name="#{name(:id)}-#{num}-d3hidden"
|
120
|
-
q.text=random_image_for(name(:raw)) + lang.text_for(:d3, lang.hide_text(name(:raw)), t )
|
121
|
-
q.shorts << name(:raw)
|
122
|
-
q.shorts << name(:raw).gsub("-"," ").gsub("_"," ")
|
123
|
-
names.each do |n|
|
124
|
-
q.shorts << n if n!=name
|
125
|
-
end
|
126
|
-
questions << q
|
127
|
-
end
|
128
|
-
|
129
|
-
# indexes = []
|
130
|
-
# exclude = ["[", "]", "(", ")", "\"" ]
|
131
|
-
# filtered[:words].each_with_index do |item,index|
|
132
|
-
# flag=true
|
133
|
-
# exclude.each { |e| flag=false if (item[:word].include?(e)) }
|
134
|
-
# indexes << index if flag
|
135
|
-
# end
|
102
|
+
# Question hidden name questions
|
103
|
+
q = Question.new(:short)
|
104
|
+
q.name = "#{name(:id)}-#{num}-d3hidden"
|
105
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d3, lang.hide_text(name(:raw)), t)
|
106
|
+
q.shorts << name(:raw)
|
107
|
+
q.shorts << name(:raw).gsub('-', ' ').gsub('_', ' ')
|
108
|
+
concept.names.each { |n| q.shorts << n if n != name }
|
109
|
+
questions << q
|
136
110
|
|
137
|
-
#Question filtered text questions
|
138
|
-
filtered=lang.text_with_connectors(t)
|
111
|
+
# Question filtered text questions
|
112
|
+
filtered = lang.text_with_connectors(t)
|
139
113
|
indexes = filtered[:indexes]
|
140
114
|
|
141
|
-
groups =
|
142
|
-
max
|
143
|
-
groups[0,max].each do |e|
|
115
|
+
groups = indexes.combination(4).to_a.shuffle
|
116
|
+
max = (indexes.size / 4).to_i
|
117
|
+
groups[0, max].each do |e|
|
144
118
|
e.sort!
|
145
119
|
q = Question.new(:match)
|
146
120
|
q.shuffle_off
|
147
121
|
q.name = "#{name}-#{num}-d4filtered"
|
148
|
-
s = lang.build_text_from_filtered(
|
149
|
-
q.text = random_image_for(name(:raw)) + lang.text_for(:d4, name(:raw)
|
150
|
-
e.each_with_index do |value,index|
|
151
|
-
q.matching << [
|
122
|
+
s = lang.build_text_from_filtered(filtered, e)
|
123
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d4, name(:raw), s)
|
124
|
+
e.each_with_index do |value, index|
|
125
|
+
q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
|
152
126
|
end
|
153
127
|
questions << q
|
154
128
|
end
|
155
129
|
end
|
156
130
|
|
157
|
-
|
131
|
+
questions
|
158
132
|
end
|
159
|
-
|
133
|
+
# rubocop:enable Lint/BooleanSymbol
|
134
|
+
# rubocop:enable Metrics/MethodLength
|
135
|
+
# rubocop:enable Metrics/AbcSize
|
136
|
+
# rubocop:enable Metrics/BlockLength
|
137
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
138
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
160
139
|
end
|
@@ -1,13 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
require_relative 'base_stage'
|
3
4
|
require_relative '../question'
|
4
5
|
|
5
|
-
# StageF: process tables with 1 field
|
6
6
|
class StageF < BaseStage
|
7
|
+
##
|
8
|
+
# run stage_f: generate guqestion for tables with 1 field
|
9
|
+
# @param table (Table)
|
10
|
+
# @param list1 (Array) List of Rows from this table
|
11
|
+
# @param list2 (Array) List of Row from other tables
|
7
12
|
def run(table, list1, list2)
|
8
13
|
# process_table1field
|
9
14
|
questions = []
|
10
|
-
return questions if table.fields.count>1
|
15
|
+
return questions if table.fields.count > 1
|
11
16
|
|
12
17
|
questions += run_only_this_concept(table, list1)
|
13
18
|
questions += run_with_other_concepts(table, list1, list2)
|
@@ -15,29 +20,30 @@ class StageF < BaseStage
|
|
15
20
|
questions
|
16
21
|
end
|
17
22
|
|
18
|
-
private
|
23
|
+
private
|
19
24
|
|
20
25
|
def run_only_this_concept(table, list1)
|
21
26
|
questions = []
|
22
|
-
|
27
|
+
lang = concept.lang
|
28
|
+
s1 = Set.new # Set of rows from this concept
|
23
29
|
list1.each { |item| s1 << item[:data][0] }
|
24
30
|
a1 = s1.to_a
|
25
31
|
a1.shuffle!
|
26
32
|
|
27
33
|
if a1.size > 3
|
28
|
-
a1.each_cons(4) do |e1,e2,e3,e4|
|
29
|
-
e = [
|
34
|
+
a1.each_cons(4) do |e1, e2, e3, e4|
|
35
|
+
e = [e1, e2, e3, e4]
|
30
36
|
questions += make_questions_with(e, table)
|
31
37
|
|
32
|
-
#Question filtered text
|
33
|
-
e = [
|
38
|
+
# Question filtered text
|
39
|
+
e = [e1, e2, e3, e4]
|
34
40
|
e.shuffle!
|
35
41
|
t = "(a) #{e[0]}, (b) #{e[1]}, (c) #{e[2]}, (d) #{e[3]}"
|
36
|
-
filtered=lang.text_with_connectors(t)
|
42
|
+
filtered = lang.text_with_connectors(t)
|
37
43
|
indexes = filtered[:indexes]
|
38
44
|
|
39
|
-
groups =
|
40
|
-
max = (indexes.size/4).to_i
|
45
|
+
groups = indexes.combination(4).to_a.shuffle
|
46
|
+
max = (indexes.size / 4).to_i
|
41
47
|
groups[0, max].each do |i|
|
42
48
|
i.sort!
|
43
49
|
q = Question.new(:match)
|
@@ -46,9 +52,10 @@ private
|
|
46
52
|
s = lang.build_text_from_filtered(filtered, i)
|
47
53
|
q.text = random_image_for(name(:raw))
|
48
54
|
q.text += lang.text_for(:f3, name(:decorated), table.fields[0].capitalize, s)
|
49
|
-
i.each_with_index do |value,index|
|
55
|
+
i.each_with_index do |value, index|
|
50
56
|
q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
|
51
57
|
end
|
58
|
+
q.matching << ['', lang.do_mistake_to(filtered[:words][rand(filtered[:words].size)][:word].downcase)]
|
52
59
|
questions << q
|
53
60
|
end
|
54
61
|
end
|
@@ -59,55 +66,57 @@ private
|
|
59
66
|
questions
|
60
67
|
end
|
61
68
|
|
62
|
-
def make_questions_with(
|
69
|
+
def make_questions_with(values, table)
|
63
70
|
questions = []
|
71
|
+
lang = concept.lang
|
64
72
|
|
65
|
-
|
73
|
+
values.shuffle!
|
66
74
|
q = Question.new(:choice)
|
67
|
-
q.name = "#{name(:id)}-#{num}-f1true#{
|
75
|
+
q.name = "#{name(:id)}-#{num}-f1true#{values.size}-#{table.name}"
|
68
76
|
q.text = random_image_for(name(:raw))
|
69
|
-
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize,
|
77
|
+
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
|
70
78
|
q.good = lang.text_for(:true)
|
71
79
|
q.bads << lang.text_for(:misspelling)
|
72
80
|
q.bads << lang.text_for(:false)
|
73
81
|
|
74
|
-
if type == 'text'
|
75
|
-
|
82
|
+
if concept.type == 'text'
|
83
|
+
values.shuffle!
|
76
84
|
q = Question.new(:short)
|
77
|
-
q.name = "#{name(:id)}-#{num}-f1short#{
|
85
|
+
q.name = "#{name(:id)}-#{num}-f1short#{values.size}-#{table.name}"
|
78
86
|
q.text = random_image_for(name(:raw))
|
79
|
-
q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize,
|
87
|
+
q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize, values.join('</li><li>'))
|
80
88
|
q.shorts << name(:raw)
|
81
89
|
q.shorts << name(:raw).tr('-_', ' ')
|
82
90
|
questions << q
|
83
91
|
|
84
|
-
|
85
|
-
save =
|
86
|
-
|
92
|
+
values.shuffle!
|
93
|
+
save = values[0]
|
94
|
+
values[0] = lang.do_mistake_to(values[0])
|
87
95
|
q = Question.new(:choice)
|
88
|
-
q.name = "#{name(:id)}-#{num}-f1name-misspelled#{
|
96
|
+
q.name = "#{name(:id)}-#{num}-f1name-misspelled#{values.size}-#{table.name}"
|
89
97
|
q.text = random_image_for(name(:raw))
|
90
|
-
q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)),
|
98
|
+
q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)), \
|
99
|
+
table.fields[0].capitalize, values.join('</li><li>'))
|
91
100
|
q.good = lang.text_for(:misspelling)
|
92
101
|
q.bads << lang.text_for(:true)
|
93
102
|
q.bads << lang.text_for(:false)
|
94
103
|
q.feedback = "Concept name #{name(:raw)} misspelled!"
|
95
|
-
|
104
|
+
values[0] = save
|
96
105
|
questions << q
|
97
106
|
end
|
98
107
|
|
99
|
-
|
100
|
-
save =
|
101
|
-
|
108
|
+
values.shuffle!
|
109
|
+
save = values[0]
|
110
|
+
values[0] = lang.do_mistake_to(values[0])
|
102
111
|
q = Question.new(:choice)
|
103
|
-
q.name = "#{name(:id)}-#{num}-f1true-misspelled#{
|
112
|
+
q.name = "#{name(:id)}-#{num}-f1true-misspelled#{values.size}-#{table.name}"
|
104
113
|
q.text = random_image_for(name(:raw))
|
105
|
-
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize,
|
114
|
+
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
|
106
115
|
q.good = lang.text_for(:misspelling)
|
107
116
|
q.bads << lang.text_for(:true)
|
108
117
|
q.bads << lang.text_for(:false)
|
109
|
-
q.feedback = "Text #{save}
|
110
|
-
|
118
|
+
q.feedback = "Text #{save} misspelled!"
|
119
|
+
values[0] = save
|
111
120
|
questions << q
|
112
121
|
end
|
113
122
|
|
@@ -133,17 +142,17 @@ private
|
|
133
142
|
q = Question.new(:choice)
|
134
143
|
q.name = "#{name(:id)}-#{num}-f1false-#{table.name}"
|
135
144
|
q.text = random_image_for(name(:raw))
|
136
|
-
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
|
137
|
-
q.good = lang.text_for(:false)
|
138
|
-
q.bads << lang.text_for(:misspelling)
|
139
|
-
q.bads << lang.text_for(:true)
|
145
|
+
q.text += concept.lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
|
146
|
+
q.good = concept.lang.text_for(:false)
|
147
|
+
q.bads << concept.lang.text_for(:misspelling)
|
148
|
+
q.bads << concept.lang.text_for(:true)
|
140
149
|
questions << q
|
141
150
|
|
142
151
|
f4 = a2.shuffle![0]
|
143
152
|
q = Question.new(:choice)
|
144
153
|
q.name = "#{name(:id)}-#{num}-f2outsider-#{table.name}"
|
145
154
|
q.text = random_image_for(name(:raw))
|
146
|
-
q.text += lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
|
155
|
+
q.text += concept.lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
|
147
156
|
q.good = f4
|
148
157
|
q.bads << e1
|
149
158
|
q.bads << e2
|
@@ -1,42 +1,49 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64_compatible' # TODO: Don't work with Moodle Gift images
|
4
3
|
require 'set'
|
5
4
|
|
6
5
|
require_relative 'base_stage'
|
7
6
|
require_relative '../question'
|
8
7
|
|
8
|
+
# range i1, i2, i3, i4
|
9
9
|
class StageI < BaseStage
|
10
|
-
#
|
11
|
-
|
10
|
+
# Stage I: process every image from <def> tag
|
11
|
+
# rubocop:disable Metrics/BlockLength
|
12
|
+
# rubocop:disable Metrics/MethodLength
|
13
|
+
# rubocop:disable Metrics/AbcSize
|
14
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
15
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
12
16
|
def run
|
13
|
-
|
14
|
-
questions
|
15
|
-
return questions unless type=="text"
|
17
|
+
questions = []
|
18
|
+
return questions unless concept.type == 'text'
|
16
19
|
|
20
|
+
lang = concept.lang
|
17
21
|
# for every <image> do this
|
18
|
-
images.each do |
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
q.
|
27
|
-
q.
|
28
|
-
q.
|
22
|
+
concept.images.each do |image|
|
23
|
+
url = image[:text]
|
24
|
+
s = Set.new [name, lang.text_for(:none)]
|
25
|
+
concept.neighbors.each { |n| s.add n[:concept].name }
|
26
|
+
a = s.to_a
|
27
|
+
|
28
|
+
# Question type <i1>: choose between 4 options
|
29
|
+
if s.count > 3
|
30
|
+
q = Question.new(:choice)
|
31
|
+
q.name = "#{name}-#{num}-i1choice"
|
32
|
+
q.text = lang.text_for(:i1, url)
|
33
|
+
q.encode = image[:file]
|
34
|
+
q.good = name
|
29
35
|
q.bads << lang.text_for(:none)
|
30
36
|
q.bads << a[2]
|
31
37
|
q.bads << a[3]
|
32
38
|
questions << q
|
33
39
|
end
|
34
40
|
|
35
|
-
#Question type <i1>: choose between 4 options, good none (Syntax error)
|
36
|
-
if s.count>3
|
37
|
-
q=Question.new(:choice)
|
38
|
-
q.name="#{name}-#{num}-i1misspelling"
|
39
|
-
q.text=lang.text_for(:i1, url
|
41
|
+
# Question type <i1>: choose between 4 options, good none (Syntax error)
|
42
|
+
if s.count > 3
|
43
|
+
q = Question.new(:choice)
|
44
|
+
q.name = "#{name}-#{num}-i1misspelling"
|
45
|
+
q.text = lang.text_for(:i1, url)
|
46
|
+
q.encode = image[:file]
|
40
47
|
q.good = lang.text_for(:none)
|
41
48
|
q.bads << lang.do_mistake_to(name)
|
42
49
|
q.bads << a[2]
|
@@ -45,96 +52,76 @@ class StageI < BaseStage
|
|
45
52
|
end
|
46
53
|
|
47
54
|
s.delete(name)
|
48
|
-
a=s.to_a
|
55
|
+
a = s.to_a
|
49
56
|
|
50
|
-
#Question type <i1>: choose between 4 options, good none
|
51
|
-
if s.count>3
|
57
|
+
# Question type <i1>: choose between 4 options, good none
|
58
|
+
if s.count > 3
|
52
59
|
q = Question.new(:choice)
|
53
|
-
q.name="#{name}-#{num}-i1none"
|
54
|
-
q.text=lang.text_for(:i1, url
|
55
|
-
q.
|
60
|
+
q.name = "#{name}-#{num}-i1none"
|
61
|
+
q.text = lang.text_for(:i1, url)
|
62
|
+
q.encode = image[:file]
|
63
|
+
q.good = lang.text_for(:none)
|
56
64
|
q.bads << a[1]
|
57
65
|
q.bads << a[2]
|
58
66
|
q.bads << a[3]
|
59
67
|
questions << q
|
60
68
|
end
|
61
69
|
|
62
|
-
#Question type <
|
70
|
+
# Question type <i2>: boolean => TRUE
|
63
71
|
q = Question.new(:boolean)
|
64
|
-
q.name="#{name}-#{num}-i2true"
|
65
|
-
q.text=lang.text_for(:i2, url, name
|
66
|
-
q.
|
72
|
+
q.name = "#{name}-#{num}-i2true"
|
73
|
+
q.text = lang.text_for(:i2, url, name)
|
74
|
+
q.encode = image[:file]
|
75
|
+
q.good = 'TRUE'
|
67
76
|
questions << q
|
68
77
|
|
69
|
-
#Question type <i2>: boolean => FALSE
|
70
|
-
if neighbors.count
|
78
|
+
# Question type <i2>: boolean => FALSE
|
79
|
+
if concept.neighbors.count.positive?
|
71
80
|
q = Question.new(:boolean)
|
72
|
-
q.name="#{name}-#{num}-i2false"
|
73
|
-
q.text=lang.text_for(:i2, url, neighbors[0][:concept].name
|
74
|
-
q.
|
81
|
+
q.name = "#{name}-#{num}-i2false"
|
82
|
+
q.text = lang.text_for(:i2, url, concept.neighbors[0][:concept].name)
|
83
|
+
q.encode = image[:file]
|
84
|
+
q.good = 'FALSE'
|
75
85
|
questions << q
|
76
86
|
end
|
77
87
|
|
78
|
-
#Question type <i3>: hidden name questions
|
88
|
+
# Question type <i3>: hidden name questions
|
79
89
|
q = Question.new(:short)
|
80
|
-
q.name="#{name}-#{num}-i3short"
|
81
|
-
q.text=lang.text_for(:i3, url, lang.hide_text(name)
|
90
|
+
q.name = "#{name}-#{num}-i3short"
|
91
|
+
q.text = lang.text_for(:i3, url, lang.hide_text(name))
|
92
|
+
q.encode = image[:file]
|
82
93
|
q.shorts << name
|
83
|
-
q.shorts << name.gsub(
|
94
|
+
q.shorts << name.gsub('-', ' ').gsub('_', ' ')
|
84
95
|
questions << q
|
85
96
|
|
86
|
-
#Question filtered text questions
|
87
|
-
texts.each do |t|
|
88
|
-
filtered=lang.text_with_connectors(t)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
q = Question.new(:match)
|
105
|
-
q.shuffle_off
|
106
|
-
q.name = "#{name}-#{num}-i4filtered"
|
107
|
-
e.sort!
|
108
|
-
s=lang.build_text_from_filtered( filtered, e )
|
109
|
-
q.text = lang.text_for(:i4, url , s)
|
110
|
-
e.each_with_index do |value,index|
|
111
|
-
q.matching << [ (index+1).to_s, filtered[:words][value][:word].downcase ]
|
112
|
-
end
|
97
|
+
# Question filtered text questions
|
98
|
+
concept.texts.each do |t|
|
99
|
+
filtered = lang.text_with_connectors(t)
|
100
|
+
next if filtered[:words].size < 4
|
101
|
+
|
102
|
+
indexes = filtered[:indexes]
|
103
|
+
groups = indexes.combination(4).to_a.shuffle
|
104
|
+
max = (indexes.size / 4).to_i
|
105
|
+
groups[0, max].each do |e|
|
106
|
+
q = Question.new(:match)
|
107
|
+
q.shuffle_off
|
108
|
+
q.name = "#{name}-#{num}-i4filtered"
|
109
|
+
q.encode = image[:file]
|
110
|
+
e.sort!
|
111
|
+
s = lang.build_text_from_filtered(filtered, e)
|
112
|
+
q.text = lang.text_for(:i4, url, s)
|
113
|
+
e.each_with_index do |value, index|
|
114
|
+
q.matching << [index.next.to_s, filtered[:words][value][:word].downcase]
|
113
115
|
end
|
114
|
-
questions << q
|
115
116
|
end
|
116
|
-
|
117
|
-
|
118
|
-
return questions
|
119
|
-
end
|
120
|
-
|
121
|
-
private
|
122
|
-
|
123
|
-
def html_for_raw_image(filename)
|
124
|
-
dirname = File.dirname(@concept_ia.filename)
|
125
|
-
filepath = File.join(dirname,filename)
|
126
|
-
content = File.open(filepath).read
|
127
|
-
content64 = Base64Compatible.encode64( content )
|
128
|
-
output =""
|
129
|
-
until(content64.nil?) do
|
130
|
-
output = output + content64[0,76]+"\n"
|
131
|
-
tmp = content64[76,9999999]
|
132
|
-
content64 = tmp
|
117
|
+
questions << q
|
118
|
+
end
|
133
119
|
end
|
134
|
-
|
135
|
-
ext = File.extname(filename)
|
136
|
-
output = "<img src='data:image/#{ext};base64,#{output}' />"
|
137
|
-
return output
|
120
|
+
questions
|
138
121
|
end
|
139
|
-
|
122
|
+
# rubocop:enable Metrics/BlockLength
|
123
|
+
# rubocop:enable Metrics/MethodLength
|
124
|
+
# rubocop:enable Metrics/AbcSize
|
125
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
126
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
140
127
|
end
|