asker-tool 2.1.5 → 2.2.1
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/README.md +13 -17
- data/bin/asker +2 -1
- data/lib/asker/ai/ai.rb +10 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/code/base_code_ai.rb +104 -0
- data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
- data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
- data/lib/asker/ai/code/problem_code_ai.rb +176 -0
- data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
- data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
- data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
- data/lib/asker/ai/concept_ai.rb +13 -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 +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 +149 -108
- data/lib/asker/application.rb +19 -11
- data/lib/asker/cli.rb +31 -44
- data/lib/asker/data/code.rb +62 -0
- data/lib/asker/data/column.rb +31 -21
- data/lib/asker/data/concept.rb +109 -65
- data/lib/asker/data/data_field.rb +14 -0
- data/lib/asker/data/project_data.rb +63 -0
- data/lib/asker/data/row.rb +75 -52
- data/lib/asker/data/table.rb +91 -42
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +51 -35
- 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 +74 -53
- data/lib/asker/displayer/concept_displayer.rb +16 -9
- data/lib/asker/displayer/stats_displayer.rb +12 -3
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +19 -11
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +13 -6
- 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} +48 -1
- data/lib/asker/files/example-concept.haml +0 -1
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/{lang/locales/fr → files/language/du}/mistakes.yaml +1 -1
- data/lib/asker/files/language/du/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
- data/lib/asker/files/language/en/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
- data/lib/asker/files/language/es/mistakes.yaml +84 -0
- data/lib/asker/files/language/es/templates.yaml +29 -0
- data/lib/asker/files/language/fr/connectors.yaml +76 -0
- data/lib/asker/{lang/locales/es → files/language/fr}/mistakes.yaml +0 -0
- data/lib/asker/files/language/fr/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
- 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/{checker.rb → input_checker.rb} +126 -49
- data/lib/asker/lang/lang.rb +17 -10
- data/lib/asker/lang/lang_factory.rb +32 -5
- data/lib/asker/lang/text_actions.rb +87 -69
- data/lib/asker/loader/code_loader.rb +4 -4
- data/lib/asker/loader/content_loader.rb +21 -19
- 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 +3 -14
- data/lib/asker/loader/haml_loader.rb +15 -0
- data/lib/asker/loader/image_url_loader.rb +8 -12
- data/lib/asker/loader/input_loader.rb +13 -15
- data/lib/asker/loader/project_loader.rb +25 -15
- data/lib/asker/logger.rb +36 -9
- data/lib/asker/skeleton.rb +23 -13
- data/lib/asker.rb +76 -42
- metadata +53 -54
- data/lib/asker/code/ai/base_code_ai.rb +0 -48
- data/lib/asker/code/code.rb +0 -53
- data/lib/asker/lang/locales/du/templates.yaml +0 -50
- data/lib/asker/lang/locales/en/templates.yaml +0 -29
- data/lib/asker/lang/locales/es/templates.yaml +0 -29
- data/lib/asker/lang/locales/fr/connectors.yaml +0 -92
- data/lib/asker/lang/locales/fr/templates.yaml +0 -29
- data/lib/asker/project.rb +0 -172
data/lib/asker/data/concept.rb
CHANGED
|
@@ -3,20 +3,35 @@
|
|
|
3
3
|
require 'rainbow'
|
|
4
4
|
require 'rexml/document'
|
|
5
5
|
|
|
6
|
-
require_relative '../project'
|
|
7
6
|
require_relative '../lang/lang_factory'
|
|
7
|
+
require_relative '../loader/embedded_file'
|
|
8
8
|
require_relative 'table'
|
|
9
9
|
require_relative 'data_field'
|
|
10
10
|
|
|
11
|
+
##
|
|
11
12
|
# Store Concept information
|
|
13
|
+
# rubocop:disable Metrics/ClassLength
|
|
14
|
+
# rubocop:disable Style/ClassVars
|
|
12
15
|
class Concept
|
|
13
|
-
attr_reader :id
|
|
14
|
-
attr_reader :
|
|
15
|
-
attr_reader :
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
attr_reader :id # Unique identifer (Integer)
|
|
17
|
+
attr_reader :lang # Lang code (By default is the same as map lang)
|
|
18
|
+
attr_reader :context # Context inherits from map
|
|
19
|
+
attr_reader :names # Names used to identify or name this concept
|
|
20
|
+
attr_reader :type # type = text -> Name values are only text
|
|
21
|
+
attr_reader :filename # Filename where this concept is defined
|
|
22
|
+
attr_reader :data # Data about this concept
|
|
23
|
+
attr_accessor :process # (Boolean) if it is necesary generate questions
|
|
24
|
+
|
|
25
|
+
@@id = 0 # Global Concept counter (concept identifier)
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Initilize Concept
|
|
29
|
+
# @param xml_data (XML)
|
|
30
|
+
# @param filename (String)
|
|
31
|
+
# @param lang_code (String)
|
|
32
|
+
# @param context (Array)
|
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
|
34
|
+
# rubocop:disable Metrics/AbcSize
|
|
20
35
|
def initialize(xml_data, filename, lang_code = 'en', context = [])
|
|
21
36
|
@@id += 1
|
|
22
37
|
@id = @@id
|
|
@@ -38,16 +53,17 @@ class Concept
|
|
|
38
53
|
|
|
39
54
|
@data = {}
|
|
40
55
|
@data[:tags] = []
|
|
41
|
-
@data[:texts] = []
|
|
42
|
-
@data[:images] = [] #
|
|
43
|
-
@data[:textfile_paths] = [] # TODO: By now, We'll treat this separated from texts
|
|
56
|
+
@data[:texts] = [] # Used by standard def inputs
|
|
57
|
+
@data[:images] = [] # Used by [type => file and type => image_url] def inputs
|
|
44
58
|
@data[:tables] = []
|
|
45
59
|
@data[:neighbors] = []
|
|
46
60
|
@data[:reference_to] = []
|
|
47
61
|
@data[:referenced_by] = []
|
|
48
62
|
|
|
49
|
-
|
|
63
|
+
read_data_from_xml(xml_data)
|
|
50
64
|
end
|
|
65
|
+
# rubocop:enable Metrics/MethodLength
|
|
66
|
+
# rubocop:enable Metrics/AbcSize
|
|
51
67
|
|
|
52
68
|
def name(option = :raw)
|
|
53
69
|
DataField.new(@names[0], @id, @type).get(option)
|
|
@@ -71,46 +87,85 @@ class Concept
|
|
|
71
87
|
@data[:neighbors].reverse!
|
|
72
88
|
end
|
|
73
89
|
|
|
90
|
+
# rubocop:disable Metrics/MethodLength
|
|
91
|
+
# rubocop:disable Metrics/AbcSize
|
|
92
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
74
93
|
def calculate_nearness_to_concept(other)
|
|
75
|
-
|
|
94
|
+
a = ProjectData.instance.get(:weights)
|
|
95
|
+
#Application.instance.config['ai']['formula_weights']
|
|
96
|
+
weights = a.split(',').map(&:to_f)
|
|
76
97
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
max1 = @context.count
|
|
99
|
+
max2 = @data[:tags].count
|
|
100
|
+
max3 = @data[:tables].count
|
|
80
101
|
|
|
81
|
-
|
|
102
|
+
alike1 = alike2 = alike3 = 0.0
|
|
82
103
|
|
|
83
104
|
# check if exists this items from concept1 into concept2
|
|
84
|
-
@context.each { |i|
|
|
85
|
-
@data[:tags].each { |i|
|
|
86
|
-
@data[:tables].each { |i|
|
|
105
|
+
@context.each { |i| alike1 += 1.0 unless other.context.index(i).nil? }
|
|
106
|
+
@data[:tags].each { |i| alike2 += 1.0 unless other.tags.index(i).nil? }
|
|
107
|
+
@data[:tables].each { |i| alike3 += 1.0 unless other.tables.index(i).nil? }
|
|
87
108
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
(
|
|
109
|
+
alike = (alike1 * weights[0] + alike2 * weights[1] + alike3 * weights[2])
|
|
110
|
+
max = (max1 * weights[0] + max2 * weights[1] + max3 * weights[2])
|
|
111
|
+
(alike * 100.0 / max)
|
|
91
112
|
end
|
|
113
|
+
# rubocop:enable Metrics/MethodLength
|
|
114
|
+
# rubocop:enable Metrics/AbcSize
|
|
115
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
92
116
|
|
|
117
|
+
# rubocop:disable Metrics/MethodLength
|
|
118
|
+
# rubocop:disable Metrics/AbcSize
|
|
93
119
|
def try_adding_references(other)
|
|
94
120
|
reference_to = 0
|
|
95
|
-
@data[:tags].each
|
|
121
|
+
@data[:tags].each do |i|
|
|
122
|
+
reference_to += 1 unless other.names.index(i.downcase).nil?
|
|
123
|
+
end
|
|
96
124
|
@data[:texts].each do |t|
|
|
97
125
|
text = t.clone
|
|
98
126
|
text.split(' ').each do |word|
|
|
99
127
|
reference_to += 1 unless other.names.index(word.downcase).nil?
|
|
100
128
|
end
|
|
101
129
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
return unless reference_to.positive?
|
|
131
|
+
|
|
132
|
+
@data[:reference_to] << other.name
|
|
133
|
+
other.data[:referenced_by] << name
|
|
134
|
+
end
|
|
135
|
+
# rubocop:enable Metrics/MethodLength
|
|
136
|
+
# rubocop:enable Metrics/AbcSize
|
|
137
|
+
|
|
138
|
+
def tags
|
|
139
|
+
@data[:tags]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def texts
|
|
143
|
+
@data[:texts]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def images
|
|
147
|
+
@data[:images]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def tables
|
|
151
|
+
@data[:tables]
|
|
106
152
|
end
|
|
107
153
|
|
|
108
|
-
def
|
|
109
|
-
@data[
|
|
154
|
+
def neighbors
|
|
155
|
+
@data[:neighbors]
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def reference_to
|
|
159
|
+
@data[:reference_to]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def referenced_by
|
|
163
|
+
@data[:referenced_by]
|
|
110
164
|
end
|
|
111
165
|
|
|
112
166
|
private
|
|
113
167
|
|
|
168
|
+
# rubocop:disable Metrics/MethodLength
|
|
114
169
|
def read_data_from_xml(xml_data)
|
|
115
170
|
xml_data.elements.each do |i|
|
|
116
171
|
case i.name
|
|
@@ -118,24 +173,17 @@ class Concept
|
|
|
118
173
|
process_names(i)
|
|
119
174
|
when 'tags'
|
|
120
175
|
process_tags(i)
|
|
121
|
-
when 'context'
|
|
122
|
-
# DEPRECATED: Don't use xml tag <context>
|
|
123
|
-
# instead define it as attibute of root xml tag
|
|
124
|
-
process_context(i)
|
|
125
|
-
when 'text'
|
|
126
|
-
# DEPRECATED: Use xml tag <def> instead of <text>
|
|
127
|
-
process_text(i)
|
|
128
176
|
when 'def'
|
|
129
177
|
process_def(i)
|
|
130
178
|
when 'table'
|
|
131
179
|
@data[:tables] << Table.new(self, i)
|
|
132
180
|
else
|
|
133
|
-
text = " [ERROR]
|
|
134
|
-
|
|
135
|
-
Project.instance.verbose msg
|
|
181
|
+
text = " [ERROR] Concept #{name} with unkown attribute: #{i.name}"
|
|
182
|
+
puts Rainbow(text).color(:red)
|
|
136
183
|
end
|
|
137
184
|
end
|
|
138
185
|
end
|
|
186
|
+
# rubocop:enable Metrics/MethodLength
|
|
139
187
|
|
|
140
188
|
def process_names(value)
|
|
141
189
|
@names = []
|
|
@@ -145,39 +193,35 @@ class Concept
|
|
|
145
193
|
end
|
|
146
194
|
|
|
147
195
|
def process_tags(value)
|
|
148
|
-
|
|
196
|
+
if value.text.nil? || value.text.size.zero?
|
|
197
|
+
puts Rainbow("[ERROR] Concept #{name} has tags empty!").red.briht
|
|
198
|
+
exit 1
|
|
199
|
+
end
|
|
200
|
+
|
|
149
201
|
@data[:tags] = value.text.split(',')
|
|
150
202
|
@data[:tags].collect!(&:strip)
|
|
151
203
|
end
|
|
152
204
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
msg += Rainbow(name).yellow.bright
|
|
156
|
-
msg += Rainbow(' move <context> tag info to <map>.').yellow
|
|
157
|
-
Project.instance.verbose msg
|
|
158
|
-
@context = value.text.split(',')
|
|
159
|
-
@context.collect!(&:strip)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def process_text(value)
|
|
163
|
-
msg = ' │ ' + Rainbow(' [DEPRECATED] Concept ').yellow
|
|
164
|
-
msg += Rainbow(name).yellow.bright
|
|
165
|
-
msg += Rainbow(' replace <text> tag by <def>.').yellow
|
|
166
|
-
Project.instance.verbose msg
|
|
167
|
-
@data[:texts] << value.text.strip
|
|
168
|
-
end
|
|
169
|
-
|
|
205
|
+
# rubocop:disable Metrics/AbcSize
|
|
206
|
+
# rubocop:disable Metrics/MethodLength
|
|
170
207
|
def process_def(value)
|
|
171
208
|
case value.attributes['type']
|
|
172
|
-
when 'image'
|
|
173
|
-
msg = "[DEBUG] Concept#read_xml: image #{Rainbow(value.text).bright}"
|
|
174
|
-
Project.instance.verbose Rainbow(msg).yellow
|
|
175
209
|
when 'image_url'
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
210
|
+
# Link with remote image
|
|
211
|
+
@data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
|
|
212
|
+
when 'file'
|
|
213
|
+
# Load local images and text files
|
|
214
|
+
@data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
|
|
215
|
+
when nil
|
|
180
216
|
@data[:texts] << value.text.strip
|
|
217
|
+
else
|
|
218
|
+
msg = "[ERROR] Unknown type: #{value.attributes['type']}"
|
|
219
|
+
puts Rainbow(msg).red.bright
|
|
220
|
+
exit 1
|
|
181
221
|
end
|
|
182
222
|
end
|
|
223
|
+
# rubocop:enable Metrics/AbcSize
|
|
224
|
+
# rubocop:enable Metrics/MethodLength
|
|
183
225
|
end
|
|
226
|
+
# rubocop:enable Metrics/ClassLength
|
|
227
|
+
# rubocop:enable Style/ClassVars
|
|
@@ -8,12 +8,19 @@
|
|
|
8
8
|
class DataField
|
|
9
9
|
attr_reader :id, :type
|
|
10
10
|
|
|
11
|
+
##
|
|
12
|
+
# initialize DataField
|
|
11
13
|
def initialize(data, id, type)
|
|
12
14
|
@data = data
|
|
13
15
|
@id = id.to_i # TODO: revise where it comes from? Is it unique value?
|
|
14
16
|
@type = type.to_sym
|
|
15
17
|
end
|
|
16
18
|
|
|
19
|
+
##
|
|
20
|
+
# Return internal data
|
|
21
|
+
# @param option (Symbol)
|
|
22
|
+
# @return String
|
|
23
|
+
# rubocop:disable Metrics/MethodLength
|
|
17
24
|
def get(option = :raw)
|
|
18
25
|
case @type
|
|
19
26
|
when :text
|
|
@@ -27,6 +34,7 @@ class DataField
|
|
|
27
34
|
end
|
|
28
35
|
raise ".get: data=#{@data}, type=#{@type}, option=#{option}"
|
|
29
36
|
end
|
|
37
|
+
# rubocop:enable Metrics/MethodLength
|
|
30
38
|
|
|
31
39
|
private
|
|
32
40
|
|
|
@@ -36,6 +44,7 @@ class DataField
|
|
|
36
44
|
@data
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
# rubocop:disable Metrics/MethodLength
|
|
39
48
|
def get_textfile_path(option)
|
|
40
49
|
case option
|
|
41
50
|
when :raw
|
|
@@ -50,7 +59,9 @@ class DataField
|
|
|
50
59
|
end
|
|
51
60
|
raise ".get_textfile_path: data=#{@data}, type=#{@type}, option=#{option}"
|
|
52
61
|
end
|
|
62
|
+
# rubocop:enable Metrics/MethodLength
|
|
53
63
|
|
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
|
54
65
|
def get_textfile_url(option)
|
|
55
66
|
case option
|
|
56
67
|
when :raw
|
|
@@ -64,7 +75,9 @@ class DataField
|
|
|
64
75
|
end
|
|
65
76
|
raise ".get_textfile_url: data=#{@data}, type=#{@type}, option=#{option}"
|
|
66
77
|
end
|
|
78
|
+
# rubocop:enable Metrics/MethodLength
|
|
67
79
|
|
|
80
|
+
# rubocop:disable Metrics/MethodLength
|
|
68
81
|
def get_image_url(option)
|
|
69
82
|
case option
|
|
70
83
|
when :raw
|
|
@@ -78,6 +91,7 @@ class DataField
|
|
|
78
91
|
end
|
|
79
92
|
raise ".get_image_url: data=#{@data}, type=#{@type}, option=#{option}"
|
|
80
93
|
end
|
|
94
|
+
# rubocop:enable Metrics/MethodLength
|
|
81
95
|
|
|
82
96
|
def to_screen(text)
|
|
83
97
|
return text[0, 7] + '...' + text[-15, 15] if text.size > 25
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'singleton'
|
|
4
|
+
|
|
5
|
+
class ProjectData
|
|
6
|
+
include Singleton
|
|
7
|
+
attr_reader :default, :param
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
reset
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def reset
|
|
14
|
+
@default = { inputbasedir: FileUtils.pwd,
|
|
15
|
+
stages: { d: true, b: true, f: true, i: true, s: true, t: true },
|
|
16
|
+
threshold: 0.5,
|
|
17
|
+
outputdir: 'output',
|
|
18
|
+
weights: '1, 1, 1' }
|
|
19
|
+
@param = {}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get(key)
|
|
23
|
+
return @param[key] unless @param[key].nil?
|
|
24
|
+
|
|
25
|
+
@default[key]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set(key, value)
|
|
29
|
+
@param[key] = value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Open new project
|
|
34
|
+
# * setting new params and
|
|
35
|
+
# * creating output files
|
|
36
|
+
# IMPORTANT: We need at least these values
|
|
37
|
+
# * process_file
|
|
38
|
+
# * inputdirs
|
|
39
|
+
# rubocop:disable Metrics/MethodLength
|
|
40
|
+
# rubocop:disable Metrics/AbcSize
|
|
41
|
+
def open
|
|
42
|
+
ext = File.extname(@param[:process_file]) || '.haml'
|
|
43
|
+
@param[:projectname] = @param[:projectname] ||
|
|
44
|
+
File.basename(@param[:process_file], ext)
|
|
45
|
+
|
|
46
|
+
@param[:logname] = "#{@param[:projectname]}-log.txt"
|
|
47
|
+
@param[:outputname] = "#{@param[:projectname]}-gift.txt"
|
|
48
|
+
@param[:lessonname] = "#{@param[:projectname]}-doc.txt"
|
|
49
|
+
@param[:yamlname] = "#{@param[:projectname]}.yaml"
|
|
50
|
+
@param[:moodlename] = "#{@param[:projectname]}-moodle.xml"
|
|
51
|
+
|
|
52
|
+
outputdir = get(:outputdir)
|
|
53
|
+
@param[:logpath] = File.join(outputdir, get(:logname))
|
|
54
|
+
@param[:outputpath] = File.join(outputdir, get(:outputname))
|
|
55
|
+
@param[:lessonpath] = File.join(outputdir, get(:lessonname))
|
|
56
|
+
@param[:yamlpath] = File.join(outputdir, get(:yamlname))
|
|
57
|
+
@param[:moodlepath] = File.join(outputdir, get(:moodlename))
|
|
58
|
+
|
|
59
|
+
Dir.mkdir(outputdir) unless Dir.exist?(outputdir)
|
|
60
|
+
end
|
|
61
|
+
# rubocop:enable Metrics/MethodLength
|
|
62
|
+
# rubocop:enable Metrics/AbcSize
|
|
63
|
+
end
|
data/lib/asker/data/row.rb
CHANGED
|
@@ -1,93 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
|
|
2
3
|
require_relative 'column'
|
|
3
4
|
|
|
5
|
+
##
|
|
6
|
+
# Row objects
|
|
4
7
|
class Row
|
|
5
8
|
attr_reader :table, :index, :id
|
|
6
9
|
attr_reader :langs, :types, :raws, :columns
|
|
7
10
|
attr_reader :simple
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
##
|
|
13
|
+
# Initialize Row Object
|
|
14
|
+
# @param table (Table)
|
|
15
|
+
# @param index (Integer)
|
|
16
|
+
# @param xml_data (XML)
|
|
17
|
+
def initialize(table, index, xml_data)
|
|
10
18
|
@table = table
|
|
11
19
|
@index = index
|
|
12
|
-
@id = @table.id
|
|
20
|
+
@id = "#{@table.id}.#{@index}"
|
|
13
21
|
@langs = @table.langs
|
|
14
22
|
@types = @table.types
|
|
15
23
|
@raws = []
|
|
16
24
|
@columns = []
|
|
17
|
-
@simple = { :
|
|
25
|
+
@simple = { lang: true, type: true }
|
|
18
26
|
read_data_from_xml(xml_data)
|
|
19
27
|
end
|
|
20
28
|
|
|
21
29
|
def simple_off(option)
|
|
22
|
-
@simple[option]=false
|
|
30
|
+
@simple[option] = false
|
|
23
31
|
@table.simple_off(option)
|
|
24
32
|
end
|
|
25
33
|
|
|
26
|
-
private
|
|
34
|
+
private
|
|
27
35
|
|
|
28
|
-
def read_data_from_xml(
|
|
29
|
-
if
|
|
30
|
-
build_row_with_1_column(
|
|
36
|
+
def read_data_from_xml(xml_data)
|
|
37
|
+
if xml_data.elements.count.zero?
|
|
38
|
+
build_row_with_1_column(xml_data)
|
|
31
39
|
else
|
|
32
|
-
|
|
40
|
+
build_row_with_n_columns(xml_data)
|
|
33
41
|
end
|
|
34
42
|
|
|
35
|
-
raise "[ERROR] Row: #{
|
|
43
|
+
raise "[ERROR] Row: #{xml_data}" unless @columns.size == @table.fields.size
|
|
36
44
|
end
|
|
37
45
|
|
|
38
|
-
def build_row_with_1_column(
|
|
46
|
+
def build_row_with_1_column(xml_data)
|
|
39
47
|
# When row tag only has text, we add this text as one value array
|
|
40
48
|
# This is usefull for tables with only one columns
|
|
41
|
-
@columns = [
|
|
42
|
-
@raws = [
|
|
43
|
-
|
|
44
|
-
#read attributes from XML data
|
|
45
|
-
if pXMLdata.attributes['lang'] then
|
|
46
|
-
code = pXMLdata.attributes['lang'].strip
|
|
47
|
-
if code != @langs[0].code then
|
|
48
|
-
@langs = [ LangFactory.instance.get(code) ]
|
|
49
|
-
@simple[:lang]= false
|
|
50
|
-
@table.simple_off(:lang)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
49
|
+
@columns = [Column.new(self, @raws.size, xml_data)]
|
|
50
|
+
@raws = [xml_data.text.strip.to_s]
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@types = [ type ]
|
|
58
|
-
@simple[:type]= false
|
|
59
|
-
@table.simple_off(:type)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
52
|
+
# read attributes from XML data
|
|
53
|
+
read_lang_from_xml(xml_data)
|
|
54
|
+
read_type_from_xml(xml_data)
|
|
62
55
|
end
|
|
63
56
|
|
|
64
|
-
def
|
|
65
|
-
|
|
57
|
+
def read_lang_from_xml(xml_data)
|
|
58
|
+
return unless xml_data.attributes['lang']
|
|
59
|
+
|
|
60
|
+
code = xml_data.attributes['lang'].strip
|
|
61
|
+
return if code == @langs[0].code
|
|
62
|
+
|
|
63
|
+
@langs = [LangFactory.instance.get(code)]
|
|
64
|
+
@simple[:lang] = false
|
|
65
|
+
@table.simple_off(:lang)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def read_type_from_xml(xml_data)
|
|
69
|
+
return unless xml_data.attributes['type']
|
|
70
|
+
|
|
71
|
+
type = xml_data.attributes['type'].strip
|
|
72
|
+
return if type == @types[0]
|
|
73
|
+
|
|
74
|
+
@types = [type]
|
|
75
|
+
@simple[:type] = false
|
|
76
|
+
@table.simple_off(:type)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# rubocop:disable Metrics/MethodLength
|
|
80
|
+
def build_row_with_n_columns(xml_data)
|
|
81
|
+
xml_data.elements.each do |i|
|
|
66
82
|
case i.name
|
|
67
83
|
when 'lang'
|
|
68
|
-
|
|
69
|
-
codes = @langs.map {|i| i.code }
|
|
70
|
-
|
|
71
|
-
if j.join(",")!=codes.join(",")
|
|
72
|
-
@langs = []
|
|
73
|
-
j.each { |k| @langs << LangFactory.instance.get(k.strip.to_s) }
|
|
74
|
-
@simple[:lang]=false
|
|
75
|
-
@table.simple_off(:lang)
|
|
76
|
-
end
|
|
84
|
+
read_langs_from_xml(i)
|
|
77
85
|
when 'type'
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@simple[:type]=false
|
|
83
|
-
@table.simple_off(:type)
|
|
84
|
-
end
|
|
85
|
-
when 'col' # When row tag has several columns, we add every value to the array
|
|
86
|
-
#Column Objects
|
|
87
|
-
@columns << Column.new( self, @raws.size, i)
|
|
86
|
+
read_types_from_xml(i)
|
|
87
|
+
when 'col'
|
|
88
|
+
# When row has several columns, we add every value to the array
|
|
89
|
+
@columns << Column.new(self, @raws.size, i) # Column Objects
|
|
88
90
|
@raws << i.text.to_s
|
|
89
91
|
end
|
|
90
92
|
end
|
|
91
93
|
end
|
|
94
|
+
# rubocop:enable Metrics/MethodLength
|
|
95
|
+
|
|
96
|
+
def read_langs_from_xml(xml_data)
|
|
97
|
+
j = xml_data.text.split(',')
|
|
98
|
+
codes = @langs.map(&:code)
|
|
99
|
+
return if j.join(',') == codes.join(',')
|
|
100
|
+
|
|
101
|
+
@langs = []
|
|
102
|
+
j.each { |k| @langs << LangFactory.instance.get(k.strip.to_s) }
|
|
103
|
+
@simple[:lang] = false
|
|
104
|
+
@table.simple_off(:lang)
|
|
105
|
+
end
|
|
92
106
|
|
|
107
|
+
def read_types_from_xml(xml_data)
|
|
108
|
+
j = xml_data.text.split(',')
|
|
109
|
+
return if j.join(',') == @types.join(',')
|
|
110
|
+
|
|
111
|
+
@types = []
|
|
112
|
+
j.each { |k| @types << k.strip.to_s }
|
|
113
|
+
@simple[:type] = false
|
|
114
|
+
@table.simple_off(:type)
|
|
115
|
+
end
|
|
93
116
|
end
|