asker-tool 2.1.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -19
- 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 +12 -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 +149 -108
- data/lib/asker/application.rb +24 -7
- data/lib/asker/checker.rb +149 -52
- data/lib/asker/cli.rb +37 -32
- data/lib/asker/data/code.rb +76 -0
- data/lib/asker/data/column.rb +31 -21
- data/lib/asker/data/concept.rb +108 -65
- data/lib/asker/data/data_field.rb +14 -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 +61 -32
- data/lib/asker/{exporter/code_screen_exporter.rb → displayer/code_displayer.rb} +13 -6
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +133 -0
- data/lib/asker/displayer/concept_displayer.rb +34 -0
- data/lib/asker/displayer/stats_displayer.rb +22 -0
- data/lib/asker/exporter/code_gift_exporter.rb +10 -11
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +21 -13
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +14 -9
- data/lib/asker/exporter/concept_doc_exporter.rb +21 -14
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +21 -0
- data/lib/asker/files/{config.ini → asker.ini} +48 -1
- data/lib/asker/files/example-concept.haml +24 -8
- 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 +29 -0
- data/lib/asker/files/language/en/connectors.yaml +44 -0
- data/lib/asker/files/language/en/mistakes.yaml +37 -0
- data/lib/asker/files/language/en/templates.yaml +29 -0
- data/lib/asker/files/language/es/connectors.yaml +92 -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/files/language/fr/mistakes.yaml +82 -0
- data/lib/asker/files/language/fr/templates.yaml +29 -0
- data/lib/asker/files/language/javascript/connectors.yaml +11 -0
- data/lib/asker/files/language/javascript/mistakes.yaml +30 -0
- data/lib/asker/files/language/javascript/templates.yaml +3 -0
- data/lib/asker/files/language/math/connectors.yaml +2 -0
- data/lib/asker/files/language/math/mistakes.yaml +2 -0
- data/lib/asker/files/language/math/templates.yaml +1 -0
- data/lib/asker/files/language/python/connectors.yaml +11 -0
- data/lib/asker/files/language/python/mistakes.yaml +26 -0
- data/lib/asker/files/language/python/templates.yaml +3 -0
- data/lib/asker/files/language/ruby/connectors.yaml +11 -0
- data/lib/asker/files/language/ruby/mistakes.yaml +33 -0
- data/lib/asker/files/language/ruby/templates.yaml +3 -0
- data/lib/asker/files/language/sql/connectors.yaml +6 -0
- data/lib/asker/files/language/sql/mistakes.yaml +11 -0
- data/lib/asker/files/language/sql/templates.yaml +2 -0
- data/lib/asker/formatter/concept_string_formatter.rb +13 -9
- 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.rb +18 -12
- 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 +16 -12
- 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 +3 -12
- data/lib/asker/loader/haml_loader.rb +15 -0
- data/lib/asker/loader/image_url_loader.rb +9 -11
- data/lib/asker/loader/input_loader.rb +24 -8
- data/lib/asker/loader/project_loader.rb +42 -30
- data/lib/asker/logger.rb +30 -6
- data/lib/asker/project.rb +28 -117
- data/lib/asker/skeleton.rb +40 -29
- data/lib/asker.rb +68 -79
- metadata +57 -74
- data/docs/changelog/v2.1.md +0 -99
- data/docs/commands.md +0 -12
- data/docs/contributions.md +0 -18
- data/docs/history.md +0 -40
- data/docs/idea.md +0 -44
- data/docs/inputs/README.md +0 -39
- data/docs/inputs/code.md +0 -69
- data/docs/inputs/concepts.md +0 -142
- data/docs/inputs/jedi.md +0 -68
- data/docs/inputs/tables.md +0 -112
- data/docs/inputs/templates.md +0 -87
- data/docs/install/README.md +0 -38
- data/docs/install/manual.md +0 -26
- data/docs/install/scripts.md +0 -38
- data/docs/revise/asker-file.md +0 -41
- data/docs/revise/buenas-practicas/01-convocatoria.md +0 -30
- data/docs/revise/buenas-practicas/02-formulario.md +0 -35
- data/docs/revise/buenas-practicas/03-descripcion.md +0 -63
- data/docs/revise/buenas-practicas/04-resultados.md +0 -17
- data/docs/revise/buenas-practicas/05-reproducir.md +0 -10
- data/docs/revise/ejemplos/01/README.md +0 -27
- data/docs/revise/ejemplos/02/README.md +0 -31
- data/docs/revise/ejemplos/03/README.md +0 -31
- data/docs/revise/ejemplos/04/README.md +0 -37
- data/docs/revise/ejemplos/05/README.md +0 -25
- data/docs/revise/ejemplos/06/README.md +0 -43
- data/docs/revise/ejemplos/README.md +0 -11
- data/docs/revise/projects.md +0 -74
- data/lib/asker/code/ai/base_code_ai.rb +0 -48
- data/lib/asker/code/code.rb +0 -53
- data/lib/asker/exporter/concept_ai_screen_exporter.rb +0 -115
- data/lib/asker/exporter/concept_screen_exporter.rb +0 -25
- data/lib/asker/exporter/main.rb +0 -9
data/lib/asker/data/concept.rb
CHANGED
@@ -3,20 +3,37 @@
|
|
3
3
|
require 'rainbow'
|
4
4
|
require 'rexml/document'
|
5
5
|
|
6
|
-
require_relative '../
|
6
|
+
require_relative '../application'
|
7
|
+
require_relative '../logger'
|
7
8
|
require_relative '../lang/lang_factory'
|
9
|
+
require_relative '../loader/embedded_file'
|
8
10
|
require_relative 'table'
|
9
11
|
require_relative 'data_field'
|
10
12
|
|
13
|
+
##
|
11
14
|
# Store Concept information
|
15
|
+
# rubocop:disable Metrics/ClassLength
|
16
|
+
# rubocop:disable Style/ClassVars
|
12
17
|
class Concept
|
13
|
-
attr_reader :id
|
14
|
-
attr_reader :
|
15
|
-
attr_reader :
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
attr_reader :id # Unique identifer (Integer)
|
19
|
+
attr_reader :lang # Lang code (By default is the same as map lang)
|
20
|
+
attr_reader :context # Context inherits from map
|
21
|
+
attr_reader :names # Names used to identify or name this concept
|
22
|
+
attr_reader :type # type = text -> Name values are only text
|
23
|
+
attr_reader :filename # Filename where this concept is defined
|
24
|
+
attr_reader :data # Data about this concept
|
25
|
+
attr_accessor :process # (Boolean) if it is necesary generate questions
|
26
|
+
|
27
|
+
@@id = 0 # Global Concept counter
|
28
|
+
|
29
|
+
##
|
30
|
+
# Initilize Concept
|
31
|
+
# @param xml_data (XML)
|
32
|
+
# @param filename (String)
|
33
|
+
# @param lang_code (String)
|
34
|
+
# @param context (Array)
|
35
|
+
# rubocop:disable Metrics/MethodLength
|
36
|
+
# rubocop:disable Metrics/AbcSize
|
20
37
|
def initialize(xml_data, filename, lang_code = 'en', context = [])
|
21
38
|
@@id += 1
|
22
39
|
@id = @@id
|
@@ -38,16 +55,17 @@ class Concept
|
|
38
55
|
|
39
56
|
@data = {}
|
40
57
|
@data[:tags] = []
|
41
|
-
@data[:texts] = []
|
42
|
-
@data[:images] = [] #
|
43
|
-
@data[:textfile_paths] = [] # TODO: By now, We'll treat this separated from texts
|
58
|
+
@data[:texts] = [] # Used by standard def inputs
|
59
|
+
@data[:images] = [] # Used by [type => file and type => image_url] def inputs
|
44
60
|
@data[:tables] = []
|
45
61
|
@data[:neighbors] = []
|
46
62
|
@data[:reference_to] = []
|
47
63
|
@data[:referenced_by] = []
|
48
64
|
|
49
|
-
|
65
|
+
read_data_from_xml(xml_data)
|
50
66
|
end
|
67
|
+
# rubocop:enable Metrics/MethodLength
|
68
|
+
# rubocop:enable Metrics/AbcSize
|
51
69
|
|
52
70
|
def name(option = :raw)
|
53
71
|
DataField.new(@names[0], @id, @type).get(option)
|
@@ -71,46 +89,84 @@ class Concept
|
|
71
89
|
@data[:neighbors].reverse!
|
72
90
|
end
|
73
91
|
|
92
|
+
# rubocop:disable Metrics/MethodLength
|
93
|
+
# rubocop:disable Metrics/AbcSize
|
94
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
74
95
|
def calculate_nearness_to_concept(other)
|
75
|
-
|
96
|
+
a = Application.instance.config['ai']['formula_weights']
|
97
|
+
weights = a.split(',').map(&:to_f)
|
76
98
|
|
77
|
-
|
78
|
-
|
79
|
-
|
99
|
+
max1 = @context.count
|
100
|
+
max2 = @data[:tags].count
|
101
|
+
max3 = @data[:tables].count
|
80
102
|
|
81
|
-
|
103
|
+
alike1 = alike2 = alike3 = 0.0
|
82
104
|
|
83
105
|
# check if exists this items from concept1 into concept2
|
84
|
-
@context.each { |i|
|
85
|
-
@data[:tags].each { |i|
|
86
|
-
@data[:tables].each { |i|
|
106
|
+
@context.each { |i| alike1 += 1.0 unless other.context.index(i).nil? }
|
107
|
+
@data[:tags].each { |i| alike2 += 1.0 unless other.tags.index(i).nil? }
|
108
|
+
@data[:tables].each { |i| alike3 += 1.0 unless other.tables.index(i).nil? }
|
87
109
|
|
88
|
-
|
89
|
-
|
90
|
-
(
|
110
|
+
alike = (alike1 * weights[0] + alike2 * weights[1] + alike3 * weights[2])
|
111
|
+
max = (max1 * weights[0] + max2 * weights[1] + max3 * weights[2])
|
112
|
+
(alike * 100.0 / max)
|
91
113
|
end
|
114
|
+
# rubocop:enable Metrics/MethodLength
|
115
|
+
# rubocop:enable Metrics/AbcSize
|
116
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
92
117
|
|
118
|
+
# rubocop:disable Metrics/MethodLength
|
119
|
+
# rubocop:disable Metrics/AbcSize
|
93
120
|
def try_adding_references(other)
|
94
121
|
reference_to = 0
|
95
|
-
@data[:tags].each
|
122
|
+
@data[:tags].each do |i|
|
123
|
+
reference_to += 1 unless other.names.index(i.downcase).nil?
|
124
|
+
end
|
96
125
|
@data[:texts].each do |t|
|
97
126
|
text = t.clone
|
98
127
|
text.split(' ').each do |word|
|
99
128
|
reference_to += 1 unless other.names.index(word.downcase).nil?
|
100
129
|
end
|
101
130
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
131
|
+
return unless reference_to.positive?
|
132
|
+
|
133
|
+
@data[:reference_to] << other.name
|
134
|
+
other.data[:referenced_by] << name
|
135
|
+
end
|
136
|
+
# rubocop:enable Metrics/MethodLength
|
137
|
+
# rubocop:enable Metrics/AbcSize
|
138
|
+
|
139
|
+
def tags
|
140
|
+
@data[:tags]
|
141
|
+
end
|
142
|
+
|
143
|
+
def texts
|
144
|
+
@data[:texts]
|
145
|
+
end
|
146
|
+
|
147
|
+
def images
|
148
|
+
@data[:images]
|
149
|
+
end
|
150
|
+
|
151
|
+
def tables
|
152
|
+
@data[:tables]
|
106
153
|
end
|
107
154
|
|
108
|
-
def
|
109
|
-
@data[
|
155
|
+
def neighbors
|
156
|
+
@data[:neighbors]
|
157
|
+
end
|
158
|
+
|
159
|
+
def reference_to
|
160
|
+
@data[:reference_to]
|
161
|
+
end
|
162
|
+
|
163
|
+
def referenced_by
|
164
|
+
@data[:referenced_by]
|
110
165
|
end
|
111
166
|
|
112
167
|
private
|
113
168
|
|
169
|
+
# rubocop:disable Metrics/MethodLength
|
114
170
|
def read_data_from_xml(xml_data)
|
115
171
|
xml_data.elements.each do |i|
|
116
172
|
case i.name
|
@@ -118,24 +174,17 @@ class Concept
|
|
118
174
|
process_names(i)
|
119
175
|
when 'tags'
|
120
176
|
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
177
|
when 'def'
|
129
178
|
process_def(i)
|
130
179
|
when 'table'
|
131
180
|
@data[:tables] << Table.new(self, i)
|
132
181
|
else
|
133
|
-
text = " [ERROR]
|
134
|
-
|
135
|
-
Project.instance.verbose msg
|
182
|
+
text = " [ERROR] Concept #{name} with unkown attribute: #{i.name}"
|
183
|
+
Logger.verboseln Rainbow(text).color(:red)
|
136
184
|
end
|
137
185
|
end
|
138
186
|
end
|
187
|
+
# rubocop:enable Metrics/MethodLength
|
139
188
|
|
140
189
|
def process_names(value)
|
141
190
|
@names = []
|
@@ -145,39 +194,33 @@ class Concept
|
|
145
194
|
end
|
146
195
|
|
147
196
|
def process_tags(value)
|
148
|
-
|
197
|
+
if value.text.nil? || value.text.size.zero?
|
198
|
+
Logger.verboseln Rainbow("[ERROR] Concept #{name} has tags empty!").red.briht
|
199
|
+
exit 1
|
200
|
+
end
|
201
|
+
|
149
202
|
@data[:tags] = value.text.split(',')
|
150
203
|
@data[:tags].collect!(&:strip)
|
151
204
|
end
|
152
205
|
|
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
|
-
|
206
|
+
# rubocop:disable Metrics/AbcSize
|
207
|
+
# rubocop:disable Metrics/MethodLength
|
170
208
|
def process_def(value)
|
171
209
|
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
210
|
when 'image_url'
|
176
|
-
@data[:images] << value.text.strip
|
177
|
-
when '
|
178
|
-
@data[:
|
179
|
-
|
211
|
+
@data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
|
212
|
+
when 'file'
|
213
|
+
@data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
|
214
|
+
when nil
|
180
215
|
@data[:texts] << value.text.strip
|
216
|
+
else
|
217
|
+
msg = "[ERROR] Unknown type: #{value.attributes['type']}"
|
218
|
+
Logger.verboseln Rainbow(msg).red.bright
|
219
|
+
exit 1
|
181
220
|
end
|
182
221
|
end
|
222
|
+
# rubocop:enable Metrics/AbcSize
|
223
|
+
# rubocop:enable Metrics/MethodLength
|
183
224
|
end
|
225
|
+
# rubocop:enable Metrics/ClassLength
|
226
|
+
# 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
|
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
|
data/lib/asker/data/table.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'row'
|
4
4
|
require_relative 'template'
|
@@ -6,75 +6,96 @@ require_relative 'template'
|
|
6
6
|
# Contains data table information
|
7
7
|
class Table
|
8
8
|
attr_reader :name, :id
|
9
|
-
attr_reader :fields, :
|
10
|
-
attr_reader :
|
9
|
+
attr_reader :fields, :sequence
|
10
|
+
attr_reader :langs
|
11
|
+
attr_reader :datarows # DEV: experimental replace for Row objects
|
12
|
+
attr_reader :rows # Row objects are Datarows.raws values
|
13
|
+
# Table is simple when all their rows and col has the same lang and type value
|
11
14
|
attr_reader :simple
|
12
15
|
|
16
|
+
##
|
17
|
+
# initialize Table object
|
18
|
+
# @param concept (Concept)
|
19
|
+
# @param xml_data (XML)
|
13
20
|
def initialize(concept, xml_data)
|
14
21
|
@concept = concept
|
22
|
+
read_attributes_from_xml(xml_data)
|
15
23
|
|
16
|
-
|
17
|
-
t = xml_data.attributes['fields'].to_s.strip.split(',')
|
18
|
-
t.each { |i| i.strip! }
|
19
|
-
@fields = t || []
|
24
|
+
@simple = { lang: true, type: true }
|
20
25
|
@types = ['text'] * @fields.size
|
21
26
|
@langs = [@concept.lang] * @fields.size
|
22
27
|
|
23
|
-
@
|
24
|
-
@fields.each { |i| @name=@name + '$' + i.to_s.strip.downcase}
|
25
|
-
@id = @concept.name.to_s + '.' + @name
|
26
|
-
@simple = { lang: true, type: true }
|
27
|
-
|
28
|
-
@sequence = []
|
29
|
-
if xml_data.attributes['sequence']
|
30
|
-
t = xml_data.attributes['sequence'].to_s || ""
|
31
|
-
@sequence = t.split(",")
|
32
|
-
# puts "[DEPRECATED] sequence attr on table <#{@name}>"
|
33
|
-
end
|
34
|
-
|
35
|
-
@datarows = [] #DEV experiment replace row data with row objects
|
28
|
+
@datarows = [] # DEV experiment replace row data with row objects
|
36
29
|
read_data_from_xml(xml_data)
|
37
|
-
@rows = @datarows.map
|
30
|
+
@rows = @datarows.map(&:raws)
|
38
31
|
end
|
39
32
|
|
33
|
+
##
|
34
|
+
# Return table name
|
40
35
|
def to_s
|
41
36
|
@name.to_s
|
42
37
|
end
|
43
38
|
|
39
|
+
##
|
40
|
+
# Return true if table has a sequence defined
|
44
41
|
def sequence?
|
45
|
-
@sequence.size
|
42
|
+
@sequence.size.positive?
|
46
43
|
end
|
47
44
|
|
45
|
+
##
|
46
|
+
# Return fields type:
|
47
|
+
# * types(:all) => Return an Array with all field types
|
48
|
+
# * types(index) => Return type for fields[index]
|
49
|
+
# @param index (Integer)
|
48
50
|
def types(index = :all)
|
49
51
|
@types = (['text'] * @fields.size) if @types.nil?
|
50
52
|
return @types if index == :all
|
53
|
+
|
51
54
|
@types[index]
|
52
55
|
end
|
53
56
|
|
57
|
+
##
|
58
|
+
# Set table to simple off
|
59
|
+
# * simple_off(:lang) => Set table simple lang FALSE
|
60
|
+
# * simple_off(:type) => Set table simple type FALSE
|
61
|
+
# @param option (Symbol)
|
54
62
|
def simple_off(option)
|
55
63
|
@simple[option] = false
|
56
64
|
end
|
57
65
|
|
58
66
|
private
|
59
67
|
|
68
|
+
##
|
69
|
+
# Fill:fields, name and id from XML input
|
70
|
+
# @param xml_data (XML)
|
71
|
+
# rubocop:disable Metrics/AbcSize
|
72
|
+
def read_attributes_from_xml(xml_data)
|
73
|
+
# read attributes from XML data
|
74
|
+
t = xml_data.attributes['fields'].to_s.strip.split(',')
|
75
|
+
t.each(&:strip!)
|
76
|
+
@fields = t || []
|
77
|
+
|
78
|
+
@name = ''
|
79
|
+
@fields.each { |i| @name = "#{@name}$#{i.to_s.strip.downcase}" }
|
80
|
+
@id = "#{@concept.name}.#{@name}"
|
81
|
+
|
82
|
+
@sequence = []
|
83
|
+
return unless xml_data.attributes['sequence']
|
84
|
+
|
85
|
+
@sequence = xml_data.attributes['sequence'].to_s.split(',')
|
86
|
+
end
|
87
|
+
# rubocop:enable Metrics/AbcSize
|
88
|
+
|
89
|
+
##
|
90
|
+
# Build table data from xml input
|
91
|
+
# @param xml_data (XML)
|
92
|
+
# rubocop:disable Metrics/MethodLength
|
93
|
+
# rubocop:disable Metrics/AbcSize
|
60
94
|
def read_data_from_xml(xml_data)
|
61
95
|
xml_data.elements.each do |i|
|
62
96
|
case i.name
|
63
97
|
when 'lang'
|
64
|
-
|
65
|
-
codes = @langs.map(&:code)
|
66
|
-
|
67
|
-
if j.join(',') != codes.join(',')
|
68
|
-
simple_off(:lang)
|
69
|
-
@langs = []
|
70
|
-
j.each do |k|
|
71
|
-
if k.strip == '*' || k.strip == ''
|
72
|
-
@langs << @concept.lang
|
73
|
-
else
|
74
|
-
@langs << LangFactory.instance.get(k.strip.to_s)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
98
|
+
read_lang_from_xml(i)
|
78
99
|
when 'row'
|
79
100
|
@datarows << Row.new(self, @datarows.size, i)
|
80
101
|
when 'sequence'
|
@@ -82,15 +103,43 @@ class Table
|
|
82
103
|
when 'template'
|
83
104
|
@datarows += Template.new(self, @datarows.size, i).datarows
|
84
105
|
when 'type'
|
85
|
-
|
86
|
-
if j.join(',') != @types.join(',')
|
87
|
-
simple_off(:type)
|
88
|
-
@types = []
|
89
|
-
j.each { |k| @types << k.strip.to_s }
|
90
|
-
end
|
106
|
+
read_type_from_xml(i)
|
91
107
|
else
|
92
108
|
puts Rainbow("[ERROR] concept/table#xml_data with #{i.name}").red.bright
|
93
109
|
end
|
94
110
|
end
|
95
111
|
end
|
112
|
+
# rubocop:enable Metrics/MethodLength
|
113
|
+
# rubocop:enable Metrics/AbcSize
|
114
|
+
|
115
|
+
# rubocop:disable Metrics/MethodLength
|
116
|
+
# rubocop:disable Metrics/AbcSize
|
117
|
+
# rubocop:disable Style/ConditionalAssignment
|
118
|
+
def read_lang_from_xml(xml_data)
|
119
|
+
j = xml_data.text.split(',')
|
120
|
+
codes = @langs.map(&:code)
|
121
|
+
return if j.join(',') == codes.join(',')
|
122
|
+
|
123
|
+
simple_off(:lang)
|
124
|
+
@langs = []
|
125
|
+
j.each do |k|
|
126
|
+
if ['*', ''].include? k.strip
|
127
|
+
@langs << @concept.lang
|
128
|
+
else
|
129
|
+
@langs << LangFactory.instance.get(k.strip.to_s)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
# rubocop:enable Metrics/MethodLength
|
134
|
+
# rubocop:enable Metrics/AbcSize
|
135
|
+
# rubocop:enable Style/ConditionalAssignment
|
136
|
+
|
137
|
+
def read_type_from_xml(xml_data)
|
138
|
+
j = xml_data.text.split(',')
|
139
|
+
return if j.join(',') == @types.join(',')
|
140
|
+
|
141
|
+
simple_off(:type)
|
142
|
+
@types = []
|
143
|
+
j.each { |k| @types << k.strip.to_s }
|
144
|
+
end
|
96
145
|
end
|
data/lib/asker/data/template.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
|
2
3
|
require 'rexml/document'
|
3
4
|
require_relative 'row'
|
@@ -40,7 +41,8 @@ class Template
|
|
40
41
|
|
41
42
|
def apply_vars_to_template(vars, template)
|
42
43
|
output = ''
|
43
|
-
return if vars.size.zero?
|
44
|
+
return output if vars.size.zero?
|
45
|
+
|
44
46
|
max = vars.first[1].size
|
45
47
|
(1..max).each do |index|
|
46
48
|
t = template.dup
|