asker-tool 2.1.7 → 2.2.3
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 -16
- data/lib/asker/check_input/check_haml_data.rb +264 -0
- data/lib/asker/check_input/check_table.rb +104 -0
- data/lib/asker/check_input.rb +51 -0
- data/lib/asker/cli.rb +47 -44
- 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 +7 -11
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +45 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
- data/lib/asker/exporter/concept_doc_exporter.rb +12 -2
- data/lib/asker/exporter/data_gift_exporter.rb +31 -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 +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 +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 -6
- data/lib/asker/loader/haml_loader.rb +9 -5
- 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 +36 -9
- data/lib/asker/skeleton.rb +3 -2
- data/lib/asker/version.rb +9 -0
- data/lib/asker.rb +72 -43
- metadata +60 -18
- data/lib/asker/checker.rb +0 -455
- data/lib/asker/project.rb +0 -146
@@ -1,52 +1,57 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'base_stage'
|
4
4
|
require_relative '../question'
|
5
5
|
|
6
|
+
# process_sequence
|
6
7
|
class StageS < BaseStage
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# process_sequence
|
9
|
+
# rubocop:disable Metrics/MethodLength
|
10
|
+
# rubocop:disable Metrics/AbcSize
|
11
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
12
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
13
|
+
def run(table, list1, _list2)
|
10
14
|
questions = []
|
11
|
-
return questions unless
|
12
|
-
|
13
|
-
|
14
|
-
#items
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
q
|
23
|
-
q.
|
24
|
-
q.
|
25
|
-
q.matching << [
|
26
|
-
q.matching << [ pList1[i+1][:data][0], '2º' ]
|
27
|
-
q.matching << [ pList1[i+2][:data][0], '3º' ]
|
28
|
-
q.matching << [ pList1[i+3][:data][0], '4º' ]
|
15
|
+
return questions unless table.fields.count == 1 && table.sequence? && table.sequence[0] != ''
|
16
|
+
|
17
|
+
lang = concept.lang
|
18
|
+
# Question type <d3sequence>: items are part of a sequence
|
19
|
+
if list1.count > 3
|
20
|
+
a = 0..(list1.count - 4)
|
21
|
+
a.each_entry do |i|
|
22
|
+
q = Question.new(:match)
|
23
|
+
q.name = "#{name}-#{num}-s1sequence-#{table.name}"
|
24
|
+
q.text = random_image_for(name) + lang.text_for(:s1, name, table.fields[0].capitalize, table.sequence[0])
|
25
|
+
q.matching << [list1[i + 0][:data][0], '1º']
|
26
|
+
q.matching << [list1[i + 1][:data][0], '2º']
|
27
|
+
q.matching << [list1[i + 2][:data][0], '3º']
|
28
|
+
q.matching << [list1[i + 3][:data][0], '4º']
|
29
|
+
q.matching << ['', lang.text_for(:error)]
|
29
30
|
questions << q
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
#Question type <d4sequence>: items are part of a reverse sequence
|
34
|
-
if
|
35
|
-
|
36
|
-
|
37
|
-
q=Question.new
|
34
|
+
# Question type <d4sequence>: items are part of a reverse sequence
|
35
|
+
if list1.count > 3 && table.sequence.size > 1
|
36
|
+
a = 0..(list1.count - 4)
|
37
|
+
a.each_entry do |i|
|
38
|
+
q = Question.new
|
38
39
|
q.set_match
|
39
|
-
q.name="#{name}-#{num
|
40
|
-
q.text= random_image_for(name) + lang.text_for(:s1, name,
|
41
|
-
q.matching << [
|
42
|
-
q.matching << [
|
43
|
-
q.matching << [
|
44
|
-
q.matching << [
|
40
|
+
q.name = "#{name}-#{num}-s2sequence-#{table.name}"
|
41
|
+
q.text = random_image_for(name) + lang.text_for(:s1, name, table.fields[0].capitalize, table.sequence[1])
|
42
|
+
q.matching << [list1[i + 3][:data][0], '1º']
|
43
|
+
q.matching << [list1[i + 2][:data][0], '2º']
|
44
|
+
q.matching << [list1[i + 1][:data][0], '3º']
|
45
|
+
q.matching << [list1[i + 0][:data][0], '4º']
|
46
|
+
q.matching << ['', lang.text_for(:error)]
|
45
47
|
questions << q
|
46
48
|
end
|
47
|
-
|
49
|
+
end
|
48
50
|
|
49
|
-
|
51
|
+
questions
|
50
52
|
end
|
51
|
-
|
53
|
+
# rubocop:enable Metrics/MethodLength
|
54
|
+
# rubocop:enable Metrics/AbcSize
|
55
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
56
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
52
57
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
require 'set'
|
3
4
|
require_relative 'base_stage'
|
@@ -5,56 +6,71 @@ require_relative '../question'
|
|
5
6
|
|
6
7
|
##
|
7
8
|
# StageT create questions based con Table data
|
9
|
+
# range t1-t9
|
10
|
+
# rubocop:disable Metrics/ClassLength
|
8
11
|
class StageT < BaseStage
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
+
# process_tableXfields
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
15
|
+
def run(table, row, list)
|
12
16
|
questions = []
|
13
|
-
return questions unless type == 'text'
|
14
|
-
|
15
|
-
if
|
16
|
-
questions
|
17
|
-
elsif
|
18
|
-
questions
|
19
|
-
|
20
|
-
elsif
|
21
|
-
questions
|
22
|
-
|
23
|
-
|
17
|
+
return questions unless concept.type == 'text'
|
18
|
+
|
19
|
+
if table.fields.count == 2
|
20
|
+
questions += process_table2fields(table, row, list, 0, 1)
|
21
|
+
elsif table.fields.count == 3
|
22
|
+
questions += process_table2fields(table, row, list, 0, 1)
|
23
|
+
questions += process_table2fields(table, row, list, 0, 2)
|
24
|
+
elsif table.fields.count == 4
|
25
|
+
questions += process_table2fields(table, row, list, 0, 1)
|
26
|
+
questions += process_table2fields(table, row, list, 0, 2)
|
27
|
+
questions += process_table2fields(table, row, list, 0, 3)
|
24
28
|
end
|
25
29
|
|
26
30
|
questions
|
27
31
|
end
|
32
|
+
# rubocop:enable Metrics/MethodLength
|
33
|
+
# rubocop:enable Metrics/AbcSize
|
34
|
+
|
35
|
+
private
|
28
36
|
|
29
|
-
|
30
|
-
|
37
|
+
# rubocop:disable Metrics/MethodLength
|
38
|
+
# rubocop:disable Metrics/AbcSize
|
39
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
40
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
41
|
+
def process_table2fields(table, row, list, col1, col2)
|
31
42
|
questions = []
|
43
|
+
lang = concept.lang
|
32
44
|
# create questions
|
33
45
|
|
34
|
-
# Using the column #0
|
35
|
-
s = Set.new [
|
36
|
-
|
46
|
+
# Question choice: Using the column #0
|
47
|
+
s = Set.new [row[:data][col1], lang.text_for(:none)]
|
48
|
+
list.each { |i| s.add(i[:data][col1]) }
|
37
49
|
a = s.to_a
|
38
50
|
|
39
51
|
if s.count > 3
|
40
|
-
q=Question.new
|
41
|
-
q.name="#{name}-#{num
|
42
|
-
q.text=
|
43
|
-
|
52
|
+
q = Question.new
|
53
|
+
q.name = "#{name}-#{num}-t1table-#{table.name}"
|
54
|
+
q.text = random_image_for(name) \
|
55
|
+
+ lang.text_for(:t1table, name, table.fields[col1].capitalize, \
|
56
|
+
table.fields[col2].capitalize, row[:data][col2])
|
57
|
+
q.good = row[:data][col1]
|
44
58
|
q.bads << lang.text_for(:none)
|
45
59
|
q.bads << a[2]
|
46
60
|
q.bads << a[3]
|
47
61
|
questions << q
|
48
62
|
end
|
49
63
|
|
50
|
-
s = Set.new [
|
51
|
-
|
64
|
+
s = Set.new [row[:data][col1], lang.text_for(:none)]
|
65
|
+
list.each { |i| s.add(i[:data][col1]) }
|
52
66
|
a = s.to_a
|
53
67
|
|
54
68
|
if s.count > 4
|
55
69
|
q = Question.new
|
56
|
-
q.name = "#{name}-#{num
|
57
|
-
q.text =
|
70
|
+
q.name = "#{name}-#{num}-t2table-#{table.name}"
|
71
|
+
q.text = random_image_for(name) \
|
72
|
+
+ lang.text_for(:t2table, name, table.fields[col1].capitalize, \
|
73
|
+
table.fields[col2].capitalize, row[:data][col2])
|
58
74
|
q.good = lang.text_for(:none)
|
59
75
|
q.bads << a[2]
|
60
76
|
q.bads << a[3]
|
@@ -62,15 +78,17 @@ private
|
|
62
78
|
questions << q
|
63
79
|
end
|
64
80
|
|
65
|
-
# Using the column #1
|
66
|
-
s = Set.new [
|
67
|
-
|
81
|
+
# Question choice: Using the column #1
|
82
|
+
s = Set.new [row[:data][col2], lang.text_for(:none)]
|
83
|
+
list.each { |i| s.add(i[:data][col2]) }
|
68
84
|
a = s.to_a
|
69
85
|
|
70
86
|
if s.count > 3
|
71
87
|
q = Question.new
|
72
|
-
q.name = "#{name}-#{num
|
73
|
-
q.text =
|
88
|
+
q.name = "#{name}-#{num}-t3table-#{table.name}"
|
89
|
+
q.text = random_image_for(name) \
|
90
|
+
+ lang.text_for(:t3table, name, table.fields[col1].capitalize, \
|
91
|
+
row[:data][col1], table.fields[col2].capitalize)
|
74
92
|
q.good = a[0]
|
75
93
|
q.bads << lang.text_for(:none)
|
76
94
|
q.bads << a[2]
|
@@ -78,14 +96,16 @@ private
|
|
78
96
|
questions << q
|
79
97
|
end
|
80
98
|
|
81
|
-
s = Set.new [
|
82
|
-
|
99
|
+
s = Set.new [row[:data][col2], lang.text_for(:none)]
|
100
|
+
list.each { |i| s.add(i[:data][col2]) }
|
83
101
|
a = s.to_a
|
84
102
|
|
85
103
|
if s.count > 4
|
86
104
|
q = Question.new
|
87
|
-
q.name = "#{name}-#{num
|
88
|
-
q.text =
|
105
|
+
q.name = "#{name}-#{num}-t4table-#{table.name}"
|
106
|
+
q.text = random_image_for(name) \
|
107
|
+
+ lang.text_for(:t4table, name, table.fields[col1].capitalize, \
|
108
|
+
row[:data][col1], table.fields[col2].capitalize)
|
89
109
|
q.good = lang.text_for(:none)
|
90
110
|
q.bads << a[2]
|
91
111
|
q.bads << a[3]
|
@@ -93,78 +113,99 @@ private
|
|
93
113
|
questions << q
|
94
114
|
end
|
95
115
|
|
96
|
-
# Boolean
|
116
|
+
# Question Boolean: TRUE
|
97
117
|
q = Question.new
|
98
118
|
q.set_boolean
|
99
|
-
q.name = "#{name}-#{num
|
100
|
-
q.text =
|
101
|
-
|
119
|
+
q.name = "#{name}-#{num}t5table-#{table.name}"
|
120
|
+
q.text = random_image_for(name) \
|
121
|
+
+ lang.text_for(:t5table, name, table.fields[col1].capitalize, \
|
122
|
+
row[:data][col1], table.fields[col2].capitalize, row[:data][col2])
|
123
|
+
q.good = 'TRUE'
|
102
124
|
questions << q
|
103
125
|
|
104
|
-
# Boolean
|
105
|
-
s = Set.new [
|
106
|
-
|
126
|
+
# Question Boolean: FALSE
|
127
|
+
s = Set.new [row[:data][col2]]
|
128
|
+
list.each { |i| s.add(i[:data][col2]) }
|
107
129
|
a = s.to_a
|
108
130
|
|
109
131
|
if s.count > 1
|
110
132
|
q = Question.new
|
111
133
|
q.set_boolean
|
112
|
-
q.name = "#{name}-#{num
|
113
|
-
q.text =
|
114
|
-
|
134
|
+
q.name = "#{name}-#{num}-t6table-#{table.name}"
|
135
|
+
q.text = random_image_for(name) \
|
136
|
+
+ lang.text_for(:t6table, name, table.fields[col1].capitalize, \
|
137
|
+
row[:data][col1], table.fields[col2].capitalize, a[1])
|
138
|
+
q.good = 'FALSE'
|
115
139
|
questions << q
|
116
140
|
end
|
117
141
|
|
118
|
-
s = Set.new [
|
119
|
-
|
142
|
+
s = Set.new [row[:data][col1]]
|
143
|
+
list.each { |i| s.add(i[:data][col1]) }
|
120
144
|
a = s.to_a
|
121
145
|
|
122
146
|
if s.count > 1
|
123
147
|
q = Question.new
|
124
148
|
q.set_boolean
|
125
|
-
q.name = "#{name}-#{num
|
126
|
-
q.text =
|
127
|
-
|
149
|
+
q.name = "#{name}-#{num}t7table-#{table.name}"
|
150
|
+
q.text = random_image_for(name) \
|
151
|
+
+ lang.text_for(:t7table, name, table.fields[col1].capitalize, \
|
152
|
+
a[1], table.fields[col2].capitalize, row[:data][col2])
|
153
|
+
q.good = 'FALSE'
|
128
154
|
questions << q
|
129
155
|
end
|
130
156
|
|
131
|
-
# Short
|
132
|
-
if lang.count_words(
|
157
|
+
# Question Short: column #0, 1 word
|
158
|
+
if lang.count_words(row[:data][col1]) == 1
|
133
159
|
q = Question.new
|
134
160
|
q.set_short
|
135
|
-
q.name = "#{name}-#{num
|
136
|
-
q.text =
|
137
|
-
|
138
|
-
|
161
|
+
q.name = "#{name}-#{num}t8table-#{table.name}"
|
162
|
+
q.text = random_image_for(name) \
|
163
|
+
+ lang.text_for(:t8table, name, table.fields[col2].capitalize, \
|
164
|
+
row[:data][col2], table.fields[col1].capitalize)
|
165
|
+
q.shorts << row[:data][col1]
|
166
|
+
q.shorts << row[:data][col1].gsub('-', ' ').gsub('_', ' ')
|
139
167
|
questions << q
|
140
|
-
elsif lang.count_words(
|
168
|
+
elsif lang.count_words(row[:data][col1]) == 2
|
141
169
|
q = Question.new
|
142
170
|
q.set_short
|
143
|
-
q.name = "#{name}-#{num
|
144
|
-
q.text =
|
145
|
-
|
146
|
-
|
171
|
+
q.name = "#{name}-#{num}t9table-#{table.name}"
|
172
|
+
q.text = random_image_for(name) \
|
173
|
+
+ lang.text_for(:t9table, name, table.fields[col2].capitalize, \
|
174
|
+
row[:data][col2], table.fields[col1].capitalize, \
|
175
|
+
"[#{lang.hide_text(row[:data][col1])}]", lang.count_words(row[:data][col1]))
|
176
|
+
q.shorts << row[:data][col1]
|
177
|
+
q.shorts << row[:data][col1].gsub('-', ' ').gsub('_', ' ')
|
147
178
|
questions << q
|
148
179
|
end
|
149
180
|
|
150
|
-
# Short
|
151
|
-
if lang.count_words(
|
181
|
+
# Question Short: column #1, 1 word
|
182
|
+
if lang.count_words(row[:data][col2]) == 1
|
152
183
|
q = Question.new
|
153
184
|
q.set_short
|
154
|
-
q.name = "#{name}-#{num
|
155
|
-
q.text =
|
156
|
-
|
157
|
-
|
185
|
+
q.name = "#{name}-#{num}t8table-#{table.name}"
|
186
|
+
q.text = random_image_for(name) \
|
187
|
+
+ lang.text_for(:t8table, name, table.fields[col1].capitalize, \
|
188
|
+
row[:data][col1], table.fields[col2].capitalize)
|
189
|
+
q.shorts << row[:data][col2]
|
190
|
+
q.shorts << row[:data][col2].gsub('-', ' ').gsub('_', ' ')
|
158
191
|
questions << q
|
159
|
-
elsif lang.count_words(
|
192
|
+
elsif lang.count_words(row[:data][col2]) == 2
|
160
193
|
q = Question.new
|
161
194
|
q.set_short
|
162
|
-
q.name = "#{name}-#{num
|
163
|
-
q.text =
|
164
|
-
|
165
|
-
|
195
|
+
q.name = "#{name}-#{num}t9table-#{table.name}"
|
196
|
+
q.text = random_image_for(name) \
|
197
|
+
+ lang.text_for(:t9table, name, table.fields[col1].capitalize, \
|
198
|
+
row[:data][col1], table.fields[col2].capitalize, \
|
199
|
+
"[#{lang.hide_text(row[:data][col2])}]", lang.count_words(row[:data][col2]))
|
200
|
+
q.shorts << row[:data][col2]
|
201
|
+
q.shorts << row[:data][col2].gsub('-', ' ').gsub('_', ' ')
|
166
202
|
questions << q
|
167
203
|
end
|
168
204
|
questions
|
169
205
|
end
|
206
|
+
# rubocop:enable Metrics/MethodLength
|
207
|
+
# rubocop:enable Metrics/AbcSize
|
208
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
209
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
170
210
|
end
|
211
|
+
# rubocop:enable Metrics/ClassLength
|
data/lib/asker/application.rb
CHANGED
@@ -3,31 +3,24 @@
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'inifile'
|
5
5
|
require 'rainbow'
|
6
|
+
require_relative 'version'
|
6
7
|
|
7
8
|
# Global parameters
|
8
9
|
class Application
|
9
10
|
include Singleton
|
10
|
-
|
11
|
-
VERSION = '2.1.7' # Application version
|
12
|
-
NAME = 'asker' # Application name
|
13
|
-
GEM = 'asker-tool' # Gem name
|
14
11
|
attr_reader :config
|
15
12
|
|
16
|
-
##
|
17
|
-
# Initialize Application singleton
|
18
13
|
def initialize
|
19
14
|
reset
|
20
15
|
end
|
21
16
|
|
22
|
-
##
|
23
|
-
# Initialize config values from external "config.ini" file.
|
24
|
-
# rubocop:disable Metrics/AbcSize
|
25
|
-
# rubocop:disable Metrics/MethodLength
|
26
17
|
def reset
|
27
|
-
filename = File.join(Dir.pwd,
|
28
|
-
|
29
|
-
|
30
|
-
|
18
|
+
filename = File.join(Dir.pwd,
|
19
|
+
Version::CONFIGFILE)
|
20
|
+
filename = File.join(File.dirname(__FILE__),
|
21
|
+
'files',
|
22
|
+
Version::CONFIGFILE) unless File.exist? filename
|
23
|
+
|
31
24
|
begin
|
32
25
|
@config = IniFile.load(filename)
|
33
26
|
rescue StandardError => e
|
@@ -41,6 +34,4 @@ class Application
|
|
41
34
|
Rainbow.enabled = false
|
42
35
|
Rainbow.enabled = true if @config['global']['color'].downcase == 'yes'
|
43
36
|
end
|
44
|
-
# rubocop:enable Metrics/MethodLength
|
45
|
-
# rubocop:enable Metrics/AbcSize
|
46
37
|
end
|