asker-tool 2.1.5 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|