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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -19
  3. data/bin/asker +2 -1
  4. data/lib/asker/ai/ai.rb +10 -3
  5. data/lib/asker/ai/ai_calculate.rb +20 -6
  6. data/lib/asker/ai/code/base_code_ai.rb +104 -0
  7. data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
  8. data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
  9. data/lib/asker/ai/code/problem_code_ai.rb +176 -0
  10. data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
  11. data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
  12. data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
  13. data/lib/asker/ai/concept_ai.rb +12 -2
  14. data/lib/asker/ai/question.rb +28 -6
  15. data/lib/asker/ai/stages/base_stage.rb +45 -6
  16. data/lib/asker/ai/stages/stage_b.rb +100 -50
  17. data/lib/asker/ai/stages/stage_d.rb +75 -90
  18. data/lib/asker/ai/stages/stage_f.rb +64 -36
  19. data/lib/asker/ai/stages/stage_i.rb +79 -92
  20. data/lib/asker/ai/stages/stage_s.rb +41 -36
  21. data/lib/asker/ai/stages/stage_t.rb +149 -108
  22. data/lib/asker/application.rb +24 -7
  23. data/lib/asker/checker.rb +149 -52
  24. data/lib/asker/cli.rb +37 -32
  25. data/lib/asker/data/code.rb +76 -0
  26. data/lib/asker/data/column.rb +31 -21
  27. data/lib/asker/data/concept.rb +108 -65
  28. data/lib/asker/data/data_field.rb +14 -0
  29. data/lib/asker/data/row.rb +75 -52
  30. data/lib/asker/data/table.rb +91 -42
  31. data/lib/asker/data/template.rb +3 -1
  32. data/lib/asker/data/world.rb +61 -32
  33. data/lib/asker/{exporter/code_screen_exporter.rb → displayer/code_displayer.rb} +13 -6
  34. data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
  35. data/lib/asker/displayer/concept_ai_displayer.rb +133 -0
  36. data/lib/asker/displayer/concept_displayer.rb +34 -0
  37. data/lib/asker/displayer/stats_displayer.rb +22 -0
  38. data/lib/asker/exporter/code_gift_exporter.rb +10 -11
  39. data/lib/asker/exporter/concept_ai_gift_exporter.rb +21 -13
  40. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
  41. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +14 -9
  42. data/lib/asker/exporter/concept_doc_exporter.rb +21 -14
  43. data/lib/asker/exporter/data_gift_exporter.rb +29 -0
  44. data/lib/asker/exporter/output_file_exporter.rb +21 -0
  45. data/lib/asker/files/{config.ini → asker.ini} +48 -1
  46. data/lib/asker/files/example-concept.haml +24 -8
  47. data/lib/asker/files/language/du/connectors.yaml +81 -0
  48. data/lib/asker/files/language/du/mistakes.yaml +82 -0
  49. data/lib/asker/files/language/du/templates.yaml +29 -0
  50. data/lib/asker/files/language/en/connectors.yaml +44 -0
  51. data/lib/asker/files/language/en/mistakes.yaml +37 -0
  52. data/lib/asker/files/language/en/templates.yaml +29 -0
  53. data/lib/asker/files/language/es/connectors.yaml +92 -0
  54. data/lib/asker/files/language/es/mistakes.yaml +84 -0
  55. data/lib/asker/files/language/es/templates.yaml +29 -0
  56. data/lib/asker/files/language/fr/connectors.yaml +76 -0
  57. data/lib/asker/files/language/fr/mistakes.yaml +82 -0
  58. data/lib/asker/files/language/fr/templates.yaml +29 -0
  59. data/lib/asker/files/language/javascript/connectors.yaml +11 -0
  60. data/lib/asker/files/language/javascript/mistakes.yaml +30 -0
  61. data/lib/asker/files/language/javascript/templates.yaml +3 -0
  62. data/lib/asker/files/language/math/connectors.yaml +2 -0
  63. data/lib/asker/files/language/math/mistakes.yaml +2 -0
  64. data/lib/asker/files/language/math/templates.yaml +1 -0
  65. data/lib/asker/files/language/python/connectors.yaml +11 -0
  66. data/lib/asker/files/language/python/mistakes.yaml +26 -0
  67. data/lib/asker/files/language/python/templates.yaml +3 -0
  68. data/lib/asker/files/language/ruby/connectors.yaml +11 -0
  69. data/lib/asker/files/language/ruby/mistakes.yaml +33 -0
  70. data/lib/asker/files/language/ruby/templates.yaml +3 -0
  71. data/lib/asker/files/language/sql/connectors.yaml +6 -0
  72. data/lib/asker/files/language/sql/mistakes.yaml +11 -0
  73. data/lib/asker/files/language/sql/templates.yaml +2 -0
  74. data/lib/asker/formatter/concept_string_formatter.rb +13 -9
  75. data/lib/asker/formatter/moodle/matching.erb +38 -0
  76. data/lib/asker/formatter/moodle/multichoice.erb +49 -0
  77. data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
  78. data/lib/asker/formatter/moodle/truefalse.erb +47 -0
  79. data/lib/asker/formatter/question_gift_formatter.rb +30 -20
  80. data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
  81. data/lib/asker/lang/lang.rb +18 -12
  82. data/lib/asker/lang/lang_factory.rb +32 -5
  83. data/lib/asker/lang/text_actions.rb +87 -69
  84. data/lib/asker/loader/code_loader.rb +4 -4
  85. data/lib/asker/loader/content_loader.rb +16 -12
  86. data/lib/asker/loader/directory_loader.rb +3 -3
  87. data/lib/asker/loader/embedded_file.rb +42 -0
  88. data/lib/asker/loader/file_loader.rb +3 -12
  89. data/lib/asker/loader/haml_loader.rb +15 -0
  90. data/lib/asker/loader/image_url_loader.rb +9 -11
  91. data/lib/asker/loader/input_loader.rb +24 -8
  92. data/lib/asker/loader/project_loader.rb +42 -30
  93. data/lib/asker/logger.rb +30 -6
  94. data/lib/asker/project.rb +28 -117
  95. data/lib/asker/skeleton.rb +40 -29
  96. data/lib/asker.rb +68 -79
  97. metadata +57 -74
  98. data/docs/changelog/v2.1.md +0 -99
  99. data/docs/commands.md +0 -12
  100. data/docs/contributions.md +0 -18
  101. data/docs/history.md +0 -40
  102. data/docs/idea.md +0 -44
  103. data/docs/inputs/README.md +0 -39
  104. data/docs/inputs/code.md +0 -69
  105. data/docs/inputs/concepts.md +0 -142
  106. data/docs/inputs/jedi.md +0 -68
  107. data/docs/inputs/tables.md +0 -112
  108. data/docs/inputs/templates.md +0 -87
  109. data/docs/install/README.md +0 -38
  110. data/docs/install/manual.md +0 -26
  111. data/docs/install/scripts.md +0 -38
  112. data/docs/revise/asker-file.md +0 -41
  113. data/docs/revise/buenas-practicas/01-convocatoria.md +0 -30
  114. data/docs/revise/buenas-practicas/02-formulario.md +0 -35
  115. data/docs/revise/buenas-practicas/03-descripcion.md +0 -63
  116. data/docs/revise/buenas-practicas/04-resultados.md +0 -17
  117. data/docs/revise/buenas-practicas/05-reproducir.md +0 -10
  118. data/docs/revise/ejemplos/01/README.md +0 -27
  119. data/docs/revise/ejemplos/02/README.md +0 -31
  120. data/docs/revise/ejemplos/03/README.md +0 -31
  121. data/docs/revise/ejemplos/04/README.md +0 -37
  122. data/docs/revise/ejemplos/05/README.md +0 -25
  123. data/docs/revise/ejemplos/06/README.md +0 -43
  124. data/docs/revise/ejemplos/README.md +0 -11
  125. data/docs/revise/projects.md +0 -74
  126. data/lib/asker/code/ai/base_code_ai.rb +0 -48
  127. data/lib/asker/code/code.rb +0 -53
  128. data/lib/asker/exporter/concept_ai_screen_exporter.rb +0 -115
  129. data/lib/asker/exporter/concept_screen_exporter.rb +0 -25
  130. data/lib/asker/exporter/main.rb +0 -9
@@ -3,20 +3,37 @@
3
3
  require 'rainbow'
4
4
  require 'rexml/document'
5
5
 
6
- require_relative '../project'
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, :lang, :context
14
- attr_reader :names, :type, :filename
15
- attr_reader :data
16
- attr_accessor :process
17
-
18
- @@id = 0
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] = [] # TODO: By now, We'll treat images separated from texts
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
- read_data_from_xml(xml_data)
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
- weights = Project.instance.formula_weights
96
+ a = Application.instance.config['ai']['formula_weights']
97
+ weights = a.split(',').map(&:to_f)
76
98
 
77
- li_max1 = @context.count
78
- li_max2 = @data[:tags].count
79
- li_max3 = @data[:tables].count
99
+ max1 = @context.count
100
+ max2 = @data[:tags].count
101
+ max3 = @data[:tables].count
80
102
 
81
- lf_alike1 = lf_alike2 = lf_alike3 = 0.0
103
+ alike1 = alike2 = alike3 = 0.0
82
104
 
83
105
  # check if exists this items from concept1 into concept2
84
- @context.each { |i| lf_alike1 += 1.0 unless other.context.index(i).nil? }
85
- @data[:tags].each { |i| lf_alike2 += 1.0 unless other.tags.index(i).nil? }
86
- @data[:tables].each { |i| lf_alike3 += 1.0 unless other.tables.index(i).nil? }
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
- lf_alike = (lf_alike1 * weights[0] + lf_alike2 * weights[1] + lf_alike3 * weights[2])
89
- li_max = (li_max1 * weights[0] + li_max2 * weights[1] + li_max3 * weights[2])
90
- (lf_alike * 100.0 / li_max)
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 { |i| reference_to += 1 unless other.names.index(i.downcase).nil? }
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
- if reference_to.positive?
103
- @data[:reference_to] << other.name
104
- other.data[:referenced_by] << name
105
- end
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 method_missing(method)
109
- @data[method]
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] <#{i.name}> unkown XML attribute for concept #{name}"
134
- msg = Rainbow(text).color(:red)
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
- raise '[Error] tags label empty!' if value.text.nil? || value.text.size.zero?
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
- def process_context(value)
154
- msg = ' │  ' + Rainbow(' [DEPRECATED] Concept ').yellow
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 'textfile_path'
178
- @data[:textfile_paths] << value.text.strip
179
- else
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
@@ -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
- def initialize( table, index, xml_data )
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 + "." + @index.to_s
20
+ @id = "#{@table.id}.#{@index}"
13
21
  @langs = @table.langs
14
22
  @types = @table.types
15
23
  @raws = []
16
24
  @columns = []
17
- @simple = { :lang => true, :type => true }
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(pXMLdata)
29
- if pXMLdata.elements.count==0 then
30
- build_row_with_1_column(pXMLdata)
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
- build_row_with_N_columns(pXMLdata)
40
+ build_row_with_n_columns(xml_data)
33
41
  end
34
42
 
35
- raise "[ERROR] Row: #{pXMLdata}" if @columns.size!=@table.fields.size
43
+ raise "[ERROR] Row: #{xml_data}" unless @columns.size == @table.fields.size
36
44
  end
37
45
 
38
- def build_row_with_1_column(pXMLdata)
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 = [ Column.new( self, @raws.size, pXMLdata) ]
42
- @raws = [ pXMLdata.text.strip.to_s ]
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
- if pXMLdata.attributes['type'] then
55
- type = pXMLdata.attributes['type'].strip
56
- if type != @types[0] then
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 build_row_with_N_columns(pXMLdata)
65
- pXMLdata.elements.each do |i|
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
- j = i.text.split(",")
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
- j = i.text.split(",")
79
- if j.join(",")!=@types.join(",") then
80
- @types = []
81
- j.each { |k| @types << k.strip.to_s }
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
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
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, :langs, :types, :sequence
10
- attr_reader :datarows, :rows
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
- # read attributes from XML data
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
- @name = ''
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 { |r| r.raws }
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 > 0
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
- j = i.text.split(',')
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
- j = i.text.split(',')
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
@@ -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