asker-tool 2.6.0 → 2.7.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/lib/asker/ai/ai.rb +6 -6
  4. data/lib/asker/ai/ai_calculate.rb +3 -3
  5. data/lib/asker/ai/code/base_code_ai.rb +5 -30
  6. data/lib/asker/ai/code/code_ai_factory.rb +6 -12
  7. data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
  8. data/lib/asker/ai/code/python_code_ai.rb +35 -36
  9. data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
  10. data/lib/asker/ai/code/sql_code_ai.rb +20 -21
  11. data/lib/asker/ai/concept_ai.rb +12 -22
  12. data/lib/asker/ai/problem/problem_ai.rb +226 -0
  13. data/lib/asker/ai/question.rb +34 -45
  14. data/lib/asker/ai/stages/base_stage.rb +7 -7
  15. data/lib/asker/ai/stages/stage_b.rb +62 -28
  16. data/lib/asker/ai/stages/stage_d.rb +10 -10
  17. data/lib/asker/ai/stages/stage_f.rb +17 -17
  18. data/lib/asker/ai/stages/stage_i.rb +8 -18
  19. data/lib/asker/ai/stages/stage_s.rb +28 -26
  20. data/lib/asker/ai/stages/stage_t.rb +40 -51
  21. data/lib/asker/application.rb +15 -14
  22. data/lib/asker/check_input/check_haml_data.rb +52 -51
  23. data/lib/asker/check_input/check_table.rb +17 -20
  24. data/lib/asker/check_input.rb +10 -23
  25. data/lib/asker/cli.rb +43 -24
  26. data/lib/asker/data/code.rb +10 -9
  27. data/lib/asker/data/column.rb +21 -17
  28. data/lib/asker/data/concept.rb +24 -37
  29. data/lib/asker/data/data_field.rb +2 -2
  30. data/lib/asker/data/problem.rb +112 -0
  31. data/lib/asker/data/project_data.rb +11 -15
  32. data/lib/asker/data/row.rb +25 -23
  33. data/lib/asker/data/table.rb +25 -46
  34. data/lib/asker/data/template.rb +7 -7
  35. data/lib/asker/data/world.rb +3 -3
  36. data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
  37. data/lib/asker/displayer/code_displayer.rb +10 -10
  38. data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
  39. data/lib/asker/displayer/concept_ai_displayer.rb +17 -17
  40. data/lib/asker/displayer/concept_displayer.rb +4 -2
  41. data/lib/asker/displayer/problem_displayer.rb +45 -0
  42. data/lib/asker/displayer/stats_displayer.rb +7 -12
  43. data/lib/asker/exporter/code_gift_exporter.rb +2 -2
  44. data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
  45. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
  46. data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
  47. data/lib/asker/exporter/data_gift_exporter.rb +14 -15
  48. data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
  49. data/lib/asker/exporter/output_file_exporter.rb +9 -8
  50. data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
  51. data/lib/asker/files/language/ca/templates.yaml +6 -0
  52. data/lib/asker/files/language/du/templates.yaml +6 -0
  53. data/lib/asker/files/language/en/templates.yaml +7 -1
  54. data/lib/asker/files/language/es/templates.yaml +6 -0
  55. data/lib/asker/files/language/fr/templates.yaml +6 -0
  56. data/lib/asker/formatter/code_string_formatter.rb +5 -5
  57. data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
  58. data/lib/asker/formatter/concept_string_formatter.rb +6 -6
  59. data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
  60. data/lib/asker/formatter/moodle/gapfill.erb +57 -0
  61. data/lib/asker/formatter/moodle/ordering.erb +41 -0
  62. data/lib/asker/formatter/question_gift_formatter.rb +41 -14
  63. data/lib/asker/formatter/question_hash_formatter.rb +5 -6
  64. data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
  65. data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
  66. data/lib/asker/lang/lang.rb +16 -16
  67. data/lib/asker/lang/lang_factory.rb +13 -16
  68. data/lib/asker/lang/text_actions.rb +20 -18
  69. data/lib/asker/loader/code_loader.rb +10 -22
  70. data/lib/asker/loader/content_loader.rb +42 -49
  71. data/lib/asker/loader/directory_loader.rb +13 -16
  72. data/lib/asker/loader/embedded_file.rb +14 -14
  73. data/lib/asker/loader/file_loader.rb +5 -4
  74. data/lib/asker/loader/haml_loader.rb +4 -3
  75. data/lib/asker/loader/image_url_loader.rb +6 -5
  76. data/lib/asker/loader/input_loader.rb +24 -10
  77. data/lib/asker/loader/problem_loader.rb +88 -0
  78. data/lib/asker/loader/project_loader.rb +5 -12
  79. data/lib/asker/logger.rb +19 -10
  80. data/lib/asker/skeleton.rb +19 -35
  81. data/lib/asker/start.rb +44 -0
  82. data/lib/asker/version.rb +1 -1
  83. data/lib/asker.rb +7 -52
  84. metadata +12 -6
  85. data/lib/asker/ai/code/problem_code_ai.rb +0 -176
  86. data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
  87. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
data/lib/asker/cli.rb CHANGED
@@ -1,50 +1,70 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rainbow'
4
- require 'thor'
5
- require_relative 'version'
6
- require_relative '../asker'
3
+ require "rainbow"
4
+ require "thor"
5
+ require_relative "version"
6
+ require_relative "../asker"
7
7
 
8
8
  ##
9
9
  # Command Line User Interface
10
10
  class CLI < Thor
11
- map ['-h', '--help'] => 'help'
11
+ map ["-h", "--help"] => "help"
12
12
 
13
- map ['-v', '--version'] => 'version'
14
- desc 'version', 'Show the program version'
13
+ map ["-v", "--version"] => "version"
14
+ desc "version", "Show the program version"
15
15
  def version
16
16
  puts "#{Asker::NAME} version #{Asker::VERSION}"
17
17
  exit 0
18
18
  end
19
19
 
20
- map ['--init'] => 'init'
21
- desc 'init', 'Create default INI config file'
20
+ map ["--init"] => "init"
21
+ desc "init", "Create default INI config file"
22
22
  def init
23
23
  Asker.init
24
24
  exit 0
25
25
  end
26
26
 
27
- map ['new','--new'] => 'create_input'
28
- desc 'new DIRPATH', 'Create Asker demo input files'
29
- ##
30
- # Create Asker demo input files
31
- # @param dirname (String) Path to folder
27
+ map ["new", "--new"] => "create_input"
28
+ desc "new PATH", "Create Asker sample input file"
29
+ long_desc <<-LONGDESC
30
+
31
+ Create Asker sample input file (HAML format).
32
+
33
+ Examples:
34
+
35
+ (1) #{Rainbow("asker new foo/bar.haml").aqua}, Create "foo" dir and "bar.haml" file.
36
+ Path to input file can be relative or absolute.
37
+
38
+ (2) #{Rainbow("asker new foo").aqua}, Create "foo" dir and sample HAML file.
39
+ Path to directory can be relative or absolute.
40
+
41
+ LONGDESC
32
42
  def create_input(dirname)
33
43
  Asker.create_input(dirname)
34
44
  exit 0
35
45
  end
36
46
 
37
- map ['--check'] => 'check'
38
- desc 'check FILEPATH', 'Check input HAML file syntax'
47
+ map ["--check"] => "check"
48
+ desc "check FILEPATH", "Check HAML input file syntax"
49
+ long_desc <<-LONGDESC
50
+
51
+ Check HAML input file syntax.
52
+
53
+ Examples:
54
+
55
+ (*) #{Rainbow("asker check foo/bar.haml").aqua}, Check "bar.haml" input file.
56
+ Path to input file can be relative or absolute.
57
+
58
+ LONGDESC
39
59
  def check(filename)
40
60
  # Enable/disable color output
41
- Rainbow.enabled = false if options['color'] == false
61
+ Rainbow.enabled = false if options["color"] == false
42
62
  # Asker start processing input file
43
63
  Asker.check(filename)
44
64
  end
45
65
 
46
- map ['f', '-f', '--file'] => 'file'
47
- desc '[file] FILEPATH', 'Build output files, from HAML/XML input file.'
66
+ map ["f", "-f", "--file"] => "file"
67
+ desc "[file] FILEPATH", "Build output files, from HAML/XML input file."
48
68
  long_desc <<-LONGDESC
49
69
 
50
70
  Build questions about contents defined into input file specified.
@@ -53,15 +73,14 @@ class CLI < Thor
53
73
 
54
74
  Examples:
55
75
 
56
- (1) #{Rainbow('asker input/foo/foo.haml').aqua}, Build questions from HAML file.
76
+ (1) #{Rainbow("asker foo/bar.haml").aqua}, Build questions from HAML input file.
77
+ Path to input file can be relative or absolute.
57
78
 
58
- (2) #{Rainbow('asker input/foo/foo.xml').aqua}, Build questions from XML file.
59
-
60
- (3) #{Rainbow('asker projects/foo/foo.yaml').aqua}, Build questions from YAML project file.
79
+ (2) #{Rainbow("asker foo/bar.xml").aqua}, Build questions from XML input file.
80
+ Path to input file can be relative or absolute.
61
81
 
62
82
  LONGDESC
63
83
  def file(filename)
64
- # Asker start processing input file
65
84
  Asker.start(filename)
66
85
  end
67
86
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../ai/code/code_ai_factory'
3
+ require_relative "../ai/code/code_ai_factory"
4
+ require_relative "../logger"
4
5
 
5
6
  class Code
6
7
  attr_reader :dirname, :filename, :type
@@ -23,7 +24,7 @@ class Code
23
24
  end
24
25
 
25
26
  def lines_to_s(lines)
26
- out = ''
27
+ out = ""
27
28
  lines.each_with_index do |line, index|
28
29
  out << format("%2d| #{line}\n", (index + 1))
29
30
  end
@@ -36,7 +37,7 @@ class Code
36
37
  return if filepath.nil?
37
38
 
38
39
  unless File.exist? filepath
39
- puts Rainbow("[ERROR] Unkown file #{filepath}").red.bright
40
+ Logger.warn "Code: Unknown file (#{filepath})"
40
41
  return
41
42
  end
42
43
  content = File.read(filepath)
@@ -45,16 +46,16 @@ class Code
45
46
 
46
47
  def encode_and_split(text, encoding = :default)
47
48
  # Convert text to UTF-8 deleting unknown chars
48
- text ||= '' # Ensure text is not nil
49
- flag = [:default, 'UTF-8'].include? encoding
50
- return text.encode('UTF-8', invalid: :replace).split("\n") if flag
49
+ text ||= "" # Ensure text is not nil
50
+ flag = [:default, "UTF-8"].include? encoding
51
+ return text.encode("UTF-8", invalid: :replace).split("\n") if flag
51
52
 
52
53
  # Convert text from input ENCODING to UTF-8
53
- ec = Encoding::Converter.new(encoding.to_s, 'UTF-8')
54
+ ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
54
55
  begin
55
56
  text = ec.convert(text)
56
- rescue StandardError => e
57
- puts "[ERROR] Encoding: #{e}"
57
+ rescue => e
58
+ Logger.warn "Code: Encoding error (#{e}) with filename (#{@filename})"
58
59
  end
59
60
 
60
61
  text.split("\n")
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../logger"
4
+
3
5
  # Contain data information for every column
4
6
  # Params:
5
7
  # * +pRow+ - Parent row for this column
@@ -9,28 +11,27 @@ class Column
9
11
  attr_reader :row, :index, :id, :raw, :lang, :type, :simple
10
12
 
11
13
  ##
12
- # initialize Column
13
14
  # @param row (Row)
14
15
  # @param index (Integer)
15
16
  # @param xml_data (XMLdata)
16
17
  def initialize(row, index, xml_data)
17
- @row = row
18
- @index = index
19
- @id = "#{@row.id}.#{@index}"
20
- @raw = ''
21
- @lang = @row.langs[@index]
22
- @type = @row.types[@index]
23
- @simple = { lang: true, type: true }
18
+ @row = row
19
+ @index = index
20
+ @id = "#{@row.id}.#{@index}"
21
+ @raw = ""
22
+ @lang = @row.langs[@index]
23
+ @type = @row.types[@index]
24
+ @simple = {lang: true, type: true}
24
25
  read_data_from_xml(xml_data)
25
26
  end
26
27
 
27
28
  def to_html
28
29
  case @type
29
- when 'text'
30
+ when "text"
30
31
  return @raw
31
- when 'image_url'
32
- return "<img src=\"#{raw}\" alt\=\"image\">"
33
- when 'textfile_path'
32
+ when "image_url"
33
+ return "<img src=\"#{raw}\" alt=\"image\">"
34
+ when "textfile_path"
34
35
  return "<pre>#{raw}</pre>"
35
36
  end
36
37
  "ERROR type #{@type}"
@@ -39,7 +40,10 @@ class Column
39
40
  private
40
41
 
41
42
  def read_data_from_xml(xml_data)
42
- raise '[ERROR] Column with elements!' if xml_data.elements.count.positive?
43
+ if xml_data.elements.count.positive?
44
+ Logger.error "Column: Do not use elements!"
45
+ exit 1
46
+ end
43
47
 
44
48
  @raw = xml_data.text.strip.to_s
45
49
 
@@ -49,9 +53,9 @@ class Column
49
53
  end
50
54
 
51
55
  def read_lang_from_xml(xml_data)
52
- return unless xml_data.attributes['lang']
56
+ return unless xml_data.attributes["lang"]
53
57
 
54
- code = xml_data.attributes['lang'].strip
58
+ code = xml_data.attributes["lang"].strip
55
59
  return if code == @lang.code
56
60
 
57
61
  @lang = LangFactory.instance.get(code)
@@ -60,9 +64,9 @@ class Column
60
64
  end
61
65
 
62
66
  def read_type_from_xml(xml_data)
63
- return unless xml_data.attributes['type']
67
+ return unless xml_data.attributes["type"]
64
68
 
65
- type = xml_data.attributes['type'].strip
69
+ type = xml_data.attributes["type"].strip
66
70
  return if type == @type.to_s
67
71
 
68
72
  @type = type
@@ -1,14 +1,14 @@
1
- require 'rainbow'
2
- require 'rexml/document'
1
+ require "rexml/document"
3
2
 
4
- require_relative '../lang/lang_factory'
5
- require_relative '../loader/embedded_file'
6
- require_relative 'table'
7
- require_relative 'data_field'
3
+ require_relative "../lang/lang_factory"
4
+ require_relative "../loader/embedded_file"
5
+ require_relative "../logger"
6
+ require_relative "table"
7
+ require_relative "data_field"
8
8
 
9
9
  class Concept
10
10
  attr_reader :id # Unique identifer (Integer)
11
- attr_reader :lang # Lang code (By default is the same as map lang)
11
+ attr_reader :lang # Lang object
12
12
  attr_reader :context # Context inherits from map
13
13
  attr_reader :names # Names used to identify or name this concept
14
14
  attr_reader :type # type = text -> Name values are only text
@@ -24,24 +24,16 @@ class Concept
24
24
  # @param filename (String)
25
25
  # @param lang_code (String)
26
26
  # @param context (Array)
27
- def initialize(xml_data, filename, lang_code = 'en', context = [])
27
+ def initialize(xml_data, filename, lang, context)
28
28
  @@id += 1
29
29
  @id = @@id
30
30
 
31
31
  @filename = filename
32
32
  @process = false
33
- @lang = LangFactory.instance.get(lang_code)
34
-
35
- if context.class == Array
36
- @context = context
37
- elsif context.nil?
38
- @context = []
39
- else
40
- @context = context.split(',')
41
- @context.collect!(&:strip)
42
- end
43
- @names = ['concept.' + @id.to_s]
44
- @type = 'text'
33
+ @lang = lang # LangFactory.instance.get(lang_code)
34
+ @context = context
35
+ @names = ["concept." + @id.to_s]
36
+ @type = "text"
45
37
 
46
38
  @data = {}
47
39
  @data[:tags] = []
@@ -60,7 +52,7 @@ class Concept
60
52
  end
61
53
 
62
54
  def text
63
- @data[:texts][0] || '...'
55
+ @data[:texts][0] || "..."
64
56
  end
65
57
 
66
58
  def process?
@@ -71,16 +63,14 @@ class Concept
71
63
  p = calculate_nearness_to_concept(other)
72
64
  return if p.zero?
73
65
 
74
- @data[:neighbors] << { concept: other, value: p }
66
+ @data[:neighbors] << {concept: other, value: p}
75
67
  # Sort neighbors list
76
68
  @data[:neighbors].sort! { |a, b| a[:value] <=> b[:value] }
77
69
  @data[:neighbors].reverse!
78
70
  end
79
71
 
80
72
  def calculate_nearness_to_concept(other)
81
- a = ProjectData.instance.get(:weights)
82
- # Application.instance.config['ai']['formula_weights']
83
- weights = a.split(',').map(&:to_f)
73
+ weights = ProjectData.instance.get(:weights).split(",").map(&:to_f)
84
74
 
85
75
  max1 = @context.count
86
76
  max2 = @data[:tags].count
@@ -105,7 +95,7 @@ class Concept
105
95
  end
106
96
  @data[:texts].each do |t|
107
97
  text = t.clone
108
- text.split(' ').each do |word|
98
+ text.split(" ").each do |word|
109
99
  reference_to += 1 unless other.names.index(word.downcase).nil?
110
100
  end
111
101
  end
@@ -157,26 +147,25 @@ class Concept
157
147
  when "table"
158
148
  @data[:tables] << Table.new(self, i)
159
149
  else
160
- text = " [ERROR] Concept #{name} with unkown attribute: #{i.name}"
161
- puts Rainbow(text).color(:red)
150
+ Logger.warn "Concept #{name} with unkown attribute: #{i.name}"
162
151
  end
163
152
  end
164
153
  end
165
154
 
166
155
  def process_names(value)
167
156
  @names = []
168
- j = value.text.split(',')
157
+ j = value.text.split(",")
169
158
  j.each { |k| @names << k.strip }
170
- @type = value.attributes['type'].strip if value.attributes['type']
159
+ @type = value.attributes["type"].strip if value.attributes["type"]
171
160
  end
172
161
 
173
162
  def process_tags(value)
174
163
  if value.text.nil? || value.text.size.zero?
175
- puts Rainbow("[ERROR] Concept without tags: #{name} ").red.bright
176
- exit 1
164
+ Logger.warn "Concept: Concept #{name} without <tags>"
165
+ return []
177
166
  end
178
167
 
179
- @data[:tags] = value.text.split(',')
168
+ @data[:tags] = value.text.split(",")
180
169
  @data[:tags].collect!(&:strip)
181
170
  end
182
171
 
@@ -190,14 +179,12 @@ class Concept
190
179
  @data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
191
180
  when nil
192
181
  if value.text.nil?
193
- warn Rainbow("[WARN] def: without text!").yellow.bright
182
+ Logger.warn "Concept: def/text empty!"
194
183
  else
195
184
  @data[:texts] << value.text.strip
196
185
  end
197
186
  else
198
- msg = "[ERROR] Unknown type: #{value.attributes['type']}"
199
- puts Rainbow(msg).red.bright
200
- exit 1
187
+ Logger.warn "Concept: Unknown def/type (#{value.attributes["type"]})"
201
188
  end
202
189
  end
203
190
  end
@@ -12,7 +12,7 @@ class DataField
12
12
  # initialize DataField
13
13
  def initialize(data, id, type)
14
14
  @data = data
15
- @id = id.to_i # TODO: revise where it comes from? Is it unique value?
15
+ @id = id.to_i # TODO: revise where it comes from? Is it unique value?
16
16
  @type = type.to_sym
17
17
  end
18
18
 
@@ -94,7 +94,7 @@ class DataField
94
94
  # rubocop:enable Metrics/MethodLength
95
95
 
96
96
  def to_screen(text)
97
- return text[0, 7] + '...' + text[-15, 15] if text.size > 25
97
+ return text[0, 7] + "..." + text[-15, 15] if text.size > 25
98
98
 
99
99
  text
100
100
  end
@@ -0,0 +1,112 @@
1
+ require_relative "../logger"
2
+
3
+ class Problem
4
+ attr_accessor :lang
5
+ attr_accessor :context
6
+ attr_accessor :process
7
+ attr_accessor :filename
8
+ attr_accessor :varnames
9
+ attr_accessor :cases
10
+ attr_accessor :descs
11
+ attr_accessor :asks
12
+ attr_accessor :questions
13
+
14
+ @@id = 0
15
+ def initialize
16
+ @@id += 1
17
+ @id = @@id
18
+ @lang = nil
19
+ @context = nil
20
+ @process = false
21
+ @filename = "?"
22
+ @varnames = []
23
+ @cases = []
24
+ @descs = []
25
+ @asks = []
26
+ @questions = []
27
+ end
28
+
29
+ def self.from(values)
30
+ problem = Problem.new
31
+ fields = %i[filename varnames cases descs asks]
32
+ fields.each do |fieldname|
33
+ methodname = "#{fieldname}=".to_sym
34
+ problem.send(methodname, values[fieldname])
35
+ end
36
+ problem.validate
37
+ problem
38
+ end
39
+
40
+ def desc
41
+ @descs.first
42
+ end
43
+
44
+ def process?
45
+ @process
46
+ end
47
+
48
+ def name
49
+ "problem#{@id}"
50
+ end
51
+
52
+ def validate
53
+ validate_varnames
54
+ validate_cases
55
+ validate_asks
56
+ validate_descs
57
+ end
58
+
59
+ private
60
+
61
+ def validate_varnames
62
+ if !@varnames.size.zero? && @cases.size.zero?
63
+ Logger.warn "Problem: No problem/varnames defined with no problem/case"
64
+ end
65
+
66
+ @varnames.each_with_index do |varname1, index1|
67
+ @varnames.each_with_index do |varname2, index2|
68
+ next if index1 == index2
69
+ if varname1.include? varname2
70
+ Logger.error "Problem: varname(#{varname1}) includes varname(#{varname2}). Change one of them!"
71
+ exit 1
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ def validate_cases
78
+ @cases.each do |acase|
79
+ if acase.size != @varnames.size
80
+ Logger.error "Problem: problem/cases size not equal to problem/varnames size"
81
+ Logger.error " : cases size #{acase.size} (#{acase.join(",")})"
82
+ Logger.error " : varnames size #{@varnames.size} (#{@varnames.join(",")})"
83
+ exit 1
84
+ end
85
+ end
86
+ end
87
+
88
+ def validate_asks
89
+ if @asks.size.zero?
90
+ Logger.warn "Problem: No problem/ask"
91
+ end
92
+
93
+ @asks.each do |ask|
94
+ Logger.warn "Problem: No problem/ask/text" if ask[:text].nil?
95
+ if ask[:answer].nil? && ask[:steps].size.zero?
96
+ Logger.error "Problem: No problem/ask/answer and no problem/ask/steps"
97
+ exit 1
98
+ end
99
+ if !ask[:answer].nil? && !ask[:steps].size.zero?
100
+ Logger.error "Problem: Choose problem/ask/answer or problem/ask/steps"
101
+ exit 1
102
+ end
103
+ if ask[:steps].size > 0 && ask[:steps].size < 4
104
+ Logger.warn "Problem: problem/ask/steps less than 4"
105
+ end
106
+ end
107
+ end
108
+
109
+ def validate_descs
110
+ # require "debug"; binding.break
111
+ end
112
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
3
+ require "singleton"
4
4
 
5
5
  class ProjectData
6
6
  include Singleton
@@ -11,11 +11,11 @@ class ProjectData
11
11
  end
12
12
 
13
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' }
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
19
  @param = {}
20
20
  end
21
21
 
@@ -36,17 +36,15 @@ class ProjectData
36
36
  # IMPORTANT: We need at least these values
37
37
  # * process_file
38
38
  # * inputdirs
39
- # rubocop:disable Metrics/MethodLength
40
- # rubocop:disable Metrics/AbcSize
41
39
  def open
42
- ext = File.extname(@param[:process_file]) || '.haml'
40
+ ext = File.extname(@param[:process_file]) || ".haml"
43
41
  @param[:projectname] = @param[:projectname] ||
44
- File.basename(@param[:process_file], ext)
42
+ File.basename(@param[:process_file], ext)
45
43
 
46
- @param[:logname] = "#{@param[:projectname]}-log.txt"
44
+ @param[:logname] = "#{@param[:projectname]}.log"
47
45
  @param[:outputname] = "#{@param[:projectname]}-gift.txt"
48
- @param[:lessonname] = "#{@param[:projectname]}-doc.txt"
49
- @param[:yamlname] = "#{@param[:projectname]}.yaml"
46
+ @param[:lessonname] = "#{@param[:projectname]}.txt"
47
+ @param[:yamlname] = "#{@param[:projectname]}-questions.yaml"
50
48
  @param[:moodlename] = "#{@param[:projectname]}-moodle.xml"
51
49
 
52
50
  outputdir = get(:outputdir)
@@ -58,6 +56,4 @@ class ProjectData
58
56
 
59
57
  Dir.mkdir(outputdir) unless Dir.exist?(outputdir)
60
58
  end
61
- # rubocop:enable Metrics/MethodLength
62
- # rubocop:enable Metrics/AbcSize
63
59
  end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'column'
3
+ require_relative "column"
4
+ require_relative "../logger"
4
5
 
5
- ##
6
- # Row objects
7
6
  class Row
8
7
  attr_reader :table, :index, :id
9
8
  attr_reader :langs, :types, :raws, :columns
@@ -15,14 +14,14 @@ class Row
15
14
  # @param index (Integer)
16
15
  # @param xml_data (XML)
17
16
  def initialize(table, index, xml_data)
18
- @table = table
19
- @index = index
20
- @id = "#{@table.id}.#{@index}"
21
- @langs = @table.langs
22
- @types = @table.types
23
- @raws = []
17
+ @table = table
18
+ @index = index
19
+ @id = "#{@table.id}.#{@index}"
20
+ @langs = @table.langs
21
+ @types = @table.types
22
+ @raws = []
24
23
  @columns = []
25
- @simple = { lang: true, type: true }
24
+ @simple = {lang: true, type: true}
26
25
  read_data_from_xml(xml_data)
27
26
  end
28
27
 
@@ -40,14 +39,17 @@ class Row
40
39
  build_row_with_n_columns(xml_data)
41
40
  end
42
41
 
43
- raise "[ERROR] Row: #{xml_data}" unless @columns.size == @table.fields.size
42
+ unless @columns.size == @table.fields.size
43
+ Logger.error "Row: columns size != table.fields.size (#{xml_data})"
44
+ exit 1
45
+ end
44
46
  end
45
47
 
46
48
  def build_row_with_1_column(xml_data)
47
49
  # When row tag only has text, we add this text as one value array
48
50
  # This is usefull for tables with only one columns
49
51
  @columns = [Column.new(self, @raws.size, xml_data)]
50
- @raws = [xml_data.text.strip.to_s]
52
+ @raws = [xml_data.text.strip.to_s]
51
53
 
52
54
  # read attributes from XML data
53
55
  read_lang_from_xml(xml_data)
@@ -55,9 +57,9 @@ class Row
55
57
  end
56
58
 
57
59
  def read_lang_from_xml(xml_data)
58
- return unless xml_data.attributes['lang']
60
+ return unless xml_data.attributes["lang"]
59
61
 
60
- code = xml_data.attributes['lang'].strip
62
+ code = xml_data.attributes["lang"].strip
61
63
  return if code == @langs[0].code
62
64
 
63
65
  @langs = [LangFactory.instance.get(code)]
@@ -66,9 +68,9 @@ class Row
66
68
  end
67
69
 
68
70
  def read_type_from_xml(xml_data)
69
- return unless xml_data.attributes['type']
71
+ return unless xml_data.attributes["type"]
70
72
 
71
- type = xml_data.attributes['type'].strip
73
+ type = xml_data.attributes["type"].strip
72
74
  return if type == @types[0]
73
75
 
74
76
  @types = [type]
@@ -80,11 +82,11 @@ class Row
80
82
  def build_row_with_n_columns(xml_data)
81
83
  xml_data.elements.each do |i|
82
84
  case i.name
83
- when 'lang'
85
+ when "lang"
84
86
  read_langs_from_xml(i)
85
- when 'type'
87
+ when "type"
86
88
  read_types_from_xml(i)
87
- when 'col'
89
+ when "col"
88
90
  # When row has several columns, we add every value to the array
89
91
  @columns << Column.new(self, @raws.size, i) # Column Objects
90
92
  @raws << i.text.to_s
@@ -94,9 +96,9 @@ class Row
94
96
  # rubocop:enable Metrics/MethodLength
95
97
 
96
98
  def read_langs_from_xml(xml_data)
97
- j = xml_data.text.split(',')
99
+ j = xml_data.text.split(",")
98
100
  codes = @langs.map(&:code)
99
- return if j.join(',') == codes.join(',')
101
+ return if j.join(",") == codes.join(",")
100
102
 
101
103
  @langs = []
102
104
  j.each { |k| @langs << LangFactory.instance.get(k.strip.to_s) }
@@ -105,8 +107,8 @@ class Row
105
107
  end
106
108
 
107
109
  def read_types_from_xml(xml_data)
108
- j = xml_data.text.split(',')
109
- return if j.join(',') == @types.join(',')
110
+ j = xml_data.text.split(",")
111
+ return if j.join(",") == @types.join(",")
110
112
 
111
113
  @types = []
112
114
  j.each { |k| @types << k.strip.to_s }