asker-tool 2.1.7 → 2.2.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/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +1 -1
- 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 +11 -2
- 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 +100 -50
- data/lib/asker/ai/stages/stage_d.rb +75 -90
- data/lib/asker/ai/stages/stage_f.rb +64 -36
- 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 +8 -7
- data/lib/asker/checker.rb +6 -8
- data/lib/asker/cli.rb +27 -9
- data/lib/asker/data/code.rb +4 -1
- data/lib/asker/data/concept.rb +67 -21
- data/lib/asker/data/table.rb +2 -0
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +7 -4
- 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 +23 -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 +7 -11
- 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_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 +21 -19
- 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 +7 -7
- data/lib/asker/loader/directory_loader.rb +3 -3
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +1 -1
- data/lib/asker/loader/image_url_loader.rb +4 -3
- data/lib/asker/loader/input_loader.rb +1 -1
- data/lib/asker/loader/project_loader.rb +14 -5
- data/lib/asker/logger.rb +29 -4
- data/lib/asker/project.rb +14 -79
- data/lib/asker/skeleton.rb +3 -2
- data/lib/asker.rb +37 -9
- metadata +19 -22
@@ -1,160 +1,145 @@
|
|
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
|
-
#
|
10
|
-
|
10
|
+
# rubocop:disable Lint/BooleanSymbol
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
# rubocop:disable Metrics/AbcSize
|
13
|
+
# rubocop:disable Metrics/BlockLength
|
14
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
15
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
11
16
|
def run
|
12
17
|
# Stage D: process every definition, I mean every <def> tag
|
13
18
|
questions = []
|
14
|
-
return questions unless type == 'text'
|
19
|
+
return questions unless concept.type == 'text'
|
15
20
|
|
21
|
+
lang = concept.lang
|
16
22
|
# 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
|
23
|
+
concept.texts.each do |t|
|
24
|
+
s = Set.new [name(:raw), lang.text_for(:none)]
|
25
|
+
concept.neighbors.each { |n| s.add n[:concept].name(:decorated) }
|
26
|
+
a = s.to_a
|
21
27
|
|
22
28
|
# Question choose between 4 options
|
23
29
|
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)
|
30
|
+
q = Question.new(:choice)
|
31
|
+
q.name = "#{name(:id)}-#{num}-d1choose"
|
32
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
33
|
+
q.good = name(:raw)
|
28
34
|
q.bads << lang.text_for(:none)
|
29
35
|
q.bads << a[2]
|
30
36
|
q.bads << a[3]
|
31
37
|
questions << q
|
32
38
|
end
|
33
39
|
|
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)
|
40
|
+
# Question choose between 4 options, good none (Syntax error)
|
41
|
+
if s.count > 3
|
42
|
+
q = Question.new(:choice)
|
43
|
+
q.name = "#{name(:id)}-#{num}-d1none-misspelled"
|
44
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
39
45
|
q.good = lang.text_for(:none)
|
40
46
|
q.bads << lang.do_mistake_to(name(:raw))
|
41
47
|
q.bads << a[2]
|
42
48
|
q.bads << a[3]
|
43
|
-
q.feedback="Option misspelled!: #{name(:raw)}"
|
49
|
+
q.feedback = "Option misspelled!: #{name(:raw)}"
|
44
50
|
questions << q
|
45
51
|
end
|
46
52
|
|
47
53
|
s.delete(name(:raw))
|
48
|
-
a=s.to_a
|
54
|
+
a = s.to_a
|
49
55
|
|
50
|
-
#Question choose between 4 options, good none
|
51
|
-
if s.count>3
|
56
|
+
# Question choose between 4 options, good none
|
57
|
+
if s.count > 3
|
52
58
|
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)
|
59
|
+
q.name = "#{name(:id)}-#{num}-d1none"
|
60
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
|
61
|
+
q.good = lang.text_for(:none)
|
56
62
|
q.bads << a[1]
|
57
63
|
q.bads << a[2]
|
58
64
|
q.bads << a[3]
|
59
65
|
questions << q
|
60
66
|
end
|
61
67
|
|
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
|
-
|
68
|
+
# Question choice => mispelled
|
69
69
|
q = Question.new(:choice)
|
70
|
-
q.name="#{name(:id)}-#{num}-d2def-mispelled"
|
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)
|
70
|
+
q.name = "#{name(:id)}-#{num}-d2def-mispelled"
|
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)
|
73
73
|
q.bads << lang.text_for(:true)
|
74
74
|
q.bads << lang.text_for(:false)
|
75
|
-
q.feedback="Definition text mispelled!: #{t}"
|
75
|
+
q.feedback = "Definition text mispelled!: #{t}"
|
76
76
|
questions << q
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
78
|
+
# Question choice => name mispelled
|
79
|
+
q = Question.new(:choice)
|
80
|
+
q.name = "#{name(:id)}-#{num}-d2name-mispelled"
|
81
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, lang.do_mistake_to(name(:raw)), t)
|
82
|
+
q.good = lang.text_for(:misspelling)
|
83
|
+
q.bads << lang.text_for(:true)
|
84
|
+
q.bads << lang.text_for(:false)
|
85
|
+
q.feedback = "Concept name mispelled!: #{name(:raw)}"
|
86
|
+
questions << q
|
88
87
|
|
88
|
+
# Question choice => true
|
89
89
|
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
|
90
|
+
q.name = "#{name(:id)}-#{num}-d2true"
|
91
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, name(:raw), t)
|
92
92
|
q.good = lang.text_for(:true)
|
93
93
|
q.bads << lang.text_for(:misspelling)
|
94
94
|
q.bads << lang.text_for(:false)
|
95
95
|
questions << q
|
96
96
|
|
97
|
-
|
97
|
+
# Question choice => false
|
98
|
+
if a.size > 1
|
98
99
|
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)
|
100
|
+
q.name = "#{name(:id)}-#{num}-d2false-misspelled"
|
101
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d2, a[1], t)
|
101
102
|
q.good = lang.text_for(:false)
|
102
103
|
q.bads << lang.text_for(:misspelling)
|
103
104
|
q.bads << lang.text_for(:true)
|
104
105
|
questions << q
|
105
106
|
end
|
106
107
|
|
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
|
108
|
+
# Question hidden name questions
|
109
|
+
q = Question.new(:short)
|
110
|
+
q.name = "#{name(:id)}-#{num}-d3hidden"
|
111
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d3, lang.hide_text(name(:raw)), t)
|
112
|
+
q.shorts << name(:raw)
|
113
|
+
q.shorts << name(:raw).gsub('-', ' ').gsub('_', ' ')
|
114
|
+
concept.names.each { |n| q.shorts << n if n != name }
|
115
|
+
questions << q
|
136
116
|
|
137
|
-
#Question filtered text questions
|
138
|
-
filtered=lang.text_with_connectors(t)
|
117
|
+
# Question filtered text questions
|
118
|
+
filtered = lang.text_with_connectors(t)
|
139
119
|
indexes = filtered[:indexes]
|
140
120
|
|
141
|
-
groups =
|
142
|
-
max
|
143
|
-
groups[0,max].each do |e|
|
121
|
+
groups = indexes.combination(4).to_a.shuffle
|
122
|
+
max = (indexes.size / 4).to_i
|
123
|
+
groups[0, max].each do |e|
|
144
124
|
e.sort!
|
145
125
|
q = Question.new(:match)
|
146
126
|
q.shuffle_off
|
147
127
|
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 << [
|
128
|
+
s = lang.build_text_from_filtered(filtered, e)
|
129
|
+
q.text = random_image_for(name(:raw)) + lang.text_for(:d4, name(:raw), s)
|
130
|
+
e.each_with_index do |value, index|
|
131
|
+
q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
|
152
132
|
end
|
153
133
|
questions << q
|
154
134
|
end
|
155
135
|
end
|
156
136
|
|
157
|
-
|
137
|
+
questions
|
158
138
|
end
|
159
|
-
|
139
|
+
# rubocop:enable Lint/BooleanSymbol
|
140
|
+
# rubocop:enable Metrics/MethodLength
|
141
|
+
# rubocop:enable Metrics/AbcSize
|
142
|
+
# rubocop:enable Metrics/BlockLength
|
143
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
144
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
160
145
|
end
|
@@ -1,13 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
require_relative 'base_stage'
|
3
4
|
require_relative '../question'
|
4
5
|
|
5
6
|
# StageF: process tables with 1 field
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
6
8
|
class StageF < BaseStage
|
9
|
+
##
|
10
|
+
# run stage_f: generate guqestion for tables with 1 field
|
11
|
+
# @param table (Table)
|
12
|
+
# @param list1 (Array) List of Rows from this table
|
13
|
+
# @param list2 (Array) List of Row from other tables
|
7
14
|
def run(table, list1, list2)
|
8
15
|
# process_table1field
|
9
16
|
questions = []
|
10
|
-
return questions if table.fields.count>1
|
17
|
+
return questions if table.fields.count > 1
|
11
18
|
|
12
19
|
questions += run_only_this_concept(table, list1)
|
13
20
|
questions += run_with_other_concepts(table, list1, list2)
|
@@ -15,29 +22,32 @@ class StageF < BaseStage
|
|
15
22
|
questions
|
16
23
|
end
|
17
24
|
|
18
|
-
private
|
25
|
+
private
|
19
26
|
|
27
|
+
# rubocop:disable Metrics/AbcSize
|
28
|
+
# rubocop:disable Metrics/MethodLength
|
20
29
|
def run_only_this_concept(table, list1)
|
21
30
|
questions = []
|
22
|
-
|
31
|
+
lang = concept.lang
|
32
|
+
s1 = Set.new # Set of rows from this concept
|
23
33
|
list1.each { |item| s1 << item[:data][0] }
|
24
34
|
a1 = s1.to_a
|
25
35
|
a1.shuffle!
|
26
36
|
|
27
37
|
if a1.size > 3
|
28
|
-
a1.each_cons(4) do |e1,e2,e3,e4|
|
29
|
-
e = [
|
38
|
+
a1.each_cons(4) do |e1, e2, e3, e4|
|
39
|
+
e = [e1, e2, e3, e4]
|
30
40
|
questions += make_questions_with(e, table)
|
31
41
|
|
32
|
-
#Question filtered text
|
33
|
-
e = [
|
42
|
+
# Question filtered text
|
43
|
+
e = [e1, e2, e3, e4]
|
34
44
|
e.shuffle!
|
35
45
|
t = "(a) #{e[0]}, (b) #{e[1]}, (c) #{e[2]}, (d) #{e[3]}"
|
36
|
-
filtered=lang.text_with_connectors(t)
|
46
|
+
filtered = lang.text_with_connectors(t)
|
37
47
|
indexes = filtered[:indexes]
|
38
48
|
|
39
|
-
groups =
|
40
|
-
max = (indexes.size/4).to_i
|
49
|
+
groups = indexes.combination(4).to_a.shuffle
|
50
|
+
max = (indexes.size / 4).to_i
|
41
51
|
groups[0, max].each do |i|
|
42
52
|
i.sort!
|
43
53
|
q = Question.new(:match)
|
@@ -46,9 +56,10 @@ private
|
|
46
56
|
s = lang.build_text_from_filtered(filtered, i)
|
47
57
|
q.text = random_image_for(name(:raw))
|
48
58
|
q.text += lang.text_for(:f3, name(:decorated), table.fields[0].capitalize, s)
|
49
|
-
i.each_with_index do |value,index|
|
59
|
+
i.each_with_index do |value, index|
|
50
60
|
q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
|
51
61
|
end
|
62
|
+
q.matching << ['', lang.do_mistake_to(filtered[:words][rand(filtered[:words].size)][:word].downcase)]
|
52
63
|
questions << q
|
53
64
|
end
|
54
65
|
end
|
@@ -58,59 +69,72 @@ private
|
|
58
69
|
end
|
59
70
|
questions
|
60
71
|
end
|
72
|
+
# rubocop:enable Metrics/AbcSize
|
73
|
+
# rubocop:enable Metrics/MethodLength
|
61
74
|
|
62
|
-
|
75
|
+
# rubocop:disable Lint/BooleanSymbol
|
76
|
+
# rubocop:disable Metrics/MethodLength
|
77
|
+
# rubocop:disable Metrics/AbcSize
|
78
|
+
def make_questions_with(values, table)
|
63
79
|
questions = []
|
80
|
+
lang = concept.lang
|
64
81
|
|
65
|
-
|
82
|
+
values.shuffle!
|
66
83
|
q = Question.new(:choice)
|
67
|
-
q.name = "#{name(:id)}-#{num}-f1true#{
|
84
|
+
q.name = "#{name(:id)}-#{num}-f1true#{values.size}-#{table.name}"
|
68
85
|
q.text = random_image_for(name(:raw))
|
69
|
-
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize,
|
86
|
+
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
|
70
87
|
q.good = lang.text_for(:true)
|
71
88
|
q.bads << lang.text_for(:misspelling)
|
72
89
|
q.bads << lang.text_for(:false)
|
73
90
|
|
74
|
-
if type == 'text'
|
75
|
-
|
91
|
+
if concept.type == 'text'
|
92
|
+
values.shuffle!
|
76
93
|
q = Question.new(:short)
|
77
|
-
q.name = "#{name(:id)}-#{num}-f1short#{
|
94
|
+
q.name = "#{name(:id)}-#{num}-f1short#{values.size}-#{table.name}"
|
78
95
|
q.text = random_image_for(name(:raw))
|
79
|
-
q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize,
|
96
|
+
q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize, values.join('</li><li>'))
|
80
97
|
q.shorts << name(:raw)
|
81
98
|
q.shorts << name(:raw).tr('-_', ' ')
|
82
99
|
questions << q
|
83
100
|
|
84
|
-
|
85
|
-
save =
|
86
|
-
|
101
|
+
values.shuffle!
|
102
|
+
save = values[0]
|
103
|
+
values[0] = lang.do_mistake_to(values[0])
|
87
104
|
q = Question.new(:choice)
|
88
|
-
q.name = "#{name(:id)}-#{num}-f1name-misspelled#{
|
105
|
+
q.name = "#{name(:id)}-#{num}-f1name-misspelled#{values.size}-#{table.name}"
|
89
106
|
q.text = random_image_for(name(:raw))
|
90
|
-
q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)),
|
107
|
+
q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)), \
|
108
|
+
table.fields[0].capitalize, values.join('</li><li>'))
|
91
109
|
q.good = lang.text_for(:misspelling)
|
92
110
|
q.bads << lang.text_for(:true)
|
93
111
|
q.bads << lang.text_for(:false)
|
94
112
|
q.feedback = "Concept name #{name(:raw)} misspelled!"
|
95
|
-
|
113
|
+
values[0] = save
|
96
114
|
questions << q
|
97
115
|
end
|
98
116
|
|
99
|
-
|
100
|
-
save =
|
101
|
-
|
117
|
+
values.shuffle!
|
118
|
+
save = values[0]
|
119
|
+
values[0] = lang.do_mistake_to(values[0])
|
102
120
|
q = Question.new(:choice)
|
103
|
-
q.name = "#{name(:id)}-#{num}-f1true-misspelled#{
|
121
|
+
q.name = "#{name(:id)}-#{num}-f1true-misspelled#{values.size}-#{table.name}"
|
104
122
|
q.text = random_image_for(name(:raw))
|
105
|
-
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize,
|
123
|
+
q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
|
106
124
|
q.good = lang.text_for(:misspelling)
|
107
125
|
q.bads << lang.text_for(:true)
|
108
126
|
q.bads << lang.text_for(:false)
|
109
127
|
q.feedback = "Text #{save} mispelled!"
|
110
|
-
|
128
|
+
values[0] = save
|
111
129
|
questions << q
|
112
130
|
end
|
131
|
+
# rubocop:enable Lint/BooleanSymbol
|
132
|
+
# rubocop:enable Metrics/MethodLength
|
133
|
+
# rubocop:enable Metrics/AbcSize
|
113
134
|
|
135
|
+
# rubocop:disable Lint/BooleanSymbol
|
136
|
+
# rubocop:disable Metrics/MethodLength
|
137
|
+
# rubocop:disable Metrics/AbcSize
|
114
138
|
def run_with_other_concepts(table, list1, list2)
|
115
139
|
questions = []
|
116
140
|
|
@@ -133,17 +157,17 @@ private
|
|
133
157
|
q = Question.new(:choice)
|
134
158
|
q.name = "#{name(:id)}-#{num}-f1false-#{table.name}"
|
135
159
|
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)
|
160
|
+
q.text += concept.lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
|
161
|
+
q.good = concept.lang.text_for(:false)
|
162
|
+
q.bads << concept.lang.text_for(:misspelling)
|
163
|
+
q.bads << concept.lang.text_for(:true)
|
140
164
|
questions << q
|
141
165
|
|
142
166
|
f4 = a2.shuffle![0]
|
143
167
|
q = Question.new(:choice)
|
144
168
|
q.name = "#{name(:id)}-#{num}-f2outsider-#{table.name}"
|
145
169
|
q.text = random_image_for(name(:raw))
|
146
|
-
q.text += lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
|
170
|
+
q.text += concept.lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
|
147
171
|
q.good = f4
|
148
172
|
q.bads << e1
|
149
173
|
q.bads << e2
|
@@ -153,4 +177,8 @@ private
|
|
153
177
|
|
154
178
|
questions
|
155
179
|
end
|
180
|
+
# rubocop:enable Lint/BooleanSymbol
|
181
|
+
# rubocop:enable Metrics/MethodLength
|
182
|
+
# rubocop:enable Metrics/AbcSize
|
156
183
|
end
|
184
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -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
|