asker-tool 2.1.3 → 2.2.0

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 (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,6 +3,7 @@
3
3
  require 'erb'
4
4
  require 'yaml'
5
5
  require_relative 'text_actions'
6
+ require_relative '../logger'
6
7
 
7
8
  # Lang#lang
8
9
  class Lang
@@ -22,21 +23,26 @@ class Lang
22
23
  private
23
24
 
24
25
  def load_files
25
- dirbase = File.dirname(__FILE__)
26
- filename = File.join(dirbase, 'locales', @code, 'templates.yaml')
26
+ dirbase = File.join(File.dirname(__FILE__), '..', 'files', 'language')
27
+ filepath = File.join(dirbase, @code, 'templates.yaml')
28
+ @templates = load_yaml_file(filepath)
29
+ filepath = File.join(dirbase, @code, 'connectors.yaml')
30
+ @connectors = load_yaml_file(filepath)
31
+ filepath = File.join(dirbase, @code, 'mistakes.yaml')
32
+ @mistakes = load_yaml_file(filepath)
33
+ end
34
+
35
+ # rubocop:disable Security/YAMLLoad
36
+ def load_yaml_file(filepath)
27
37
  begin
28
- @templates = YAML.load(File.new(filename))
38
+ content = YAML.load(File.new(filepath))
29
39
  rescue StandardError => e
30
- p = Project.instance
31
- p.vervose "[ERROR] lang.initialize(): Reading YAML file <#{filename}>"
32
- p.vervose "[ADVISE] Revise apostrophe into string without \\ char\n"
40
+ Logger.verboseln '[ERROR] Lang.initialize():' \
41
+ " Reading YAML file <#{filepath}>"
42
+ Logger.verboseln '[ADVISE] Revise apostrophe into string without \ symbol'
33
43
  raise e
34
44
  end
35
- filename = File.join(dirbase, 'locales', @code, 'connectors.yaml')
36
- @connectors = YAML.load(File.new(filename))
37
-
38
- filename = File.join(dirbase, 'locales', @code, 'mistakes.yaml')
39
- @mistakes = YAML.load(File.new(filename))
45
+ content
40
46
  end
41
-
47
+ # rubocop:enable Security/YAMLLoad
42
48
  end
@@ -2,18 +2,45 @@
2
2
 
3
3
  require 'singleton'
4
4
  require_relative 'lang'
5
- require_relative '../project'
5
+ require_relative '../application'
6
6
 
7
- # LangFactory#get
7
+ ##
8
+ # LangFactory singleton class.
9
+ # * Read all language codes defined into configuration file
10
+ # * and load every language
11
+ # Lang objects are reused
8
12
  class LangFactory
9
13
  include Singleton
10
14
 
15
+ ##
16
+ # Read all language codes from configuration file and load every language
11
17
  def initialize
18
+ @default = Application.instance.config['languages']['default'].downcase
12
19
  @langs = {}
13
- Project.instance.locales.each { |i| @langs[i] = Lang.new(i) }
20
+ Application.instance.config['languages'].each_pair do |key, value|
21
+ code = key.downcase
22
+ next if code == 'default'
23
+
24
+ @langs[code] = Lang.new(code) if value.downcase == 'yes'
25
+ end
26
+ end
27
+
28
+ ##
29
+ # Return Lang object associated to code
30
+ # @param code (String)
31
+ def get(code)
32
+ return @langs[code] unless @langs[code].nil?
33
+
34
+ puts Rainbow("[ERROR] Unkown Lang code: #{code}").bright
35
+ puts Rainbow(' => Change input file code lang').bright
36
+ puts Rainbow(' => Revise configuration from config.ini').bright
37
+ puts Rainbow(' => Revise template files').bright
38
+ exit 1
14
39
  end
15
40
 
16
- def get(locale)
17
- @langs[locale]
41
+ ##
42
+ # Return default Lang object
43
+ def default
44
+ get(@default)
18
45
  end
19
46
  end
@@ -1,134 +1,152 @@
1
1
  # encoding: utf-8
2
2
 
3
+ ##
4
+ # Set of functions used by Lang class
3
5
  module TextActions
4
-
5
- def text_for(pOption, pText1="",pText2="",pText3="",pText4="",pText5="",pText6="",pText7="")
6
- text1=pText1
7
- text2=pText2
8
- text3=pText3
9
- text4=pText4
10
- text5=pText5
11
- text6=pText6
12
- text7=pText7
13
-
14
- # TODO: check if exists pOption before use it
15
- renderer = ERB.new(@templates[pOption])
16
- output = renderer.result(binding)
17
- return output
6
+ ##
7
+ # Return text indicated by lang code...
8
+ def text_for(option, *input)
9
+ text1 = input[0]
10
+ text2 = input[1]
11
+ text3 = input[2]
12
+ text4 = input[3]
13
+ text5 = input[4]
14
+ text6 = input[5]
15
+ text7 = input[6]
16
+
17
+ # Check if exists option before use it
18
+ raise "[ERROR] Unkown template #{option}" if @templates[option].nil?
19
+
20
+ renderer = ERB.new(@templates[option])
21
+ renderer.result(binding)
18
22
  end
19
23
 
20
- def text_filter_connectors(pText, pFilter)
21
- input_lines = pText.split(".")
24
+ ##
25
+ # Convert input text into output text struct
26
+ # @param input (String) Input text
27
+ # @param filter (Boolean) true => apply filter, false => dont filter
28
+ # @return Array
29
+ def text_filter_connectors(input, filter)
30
+ input_lines = input.split('.')
22
31
  output_lines = []
23
32
  output_words = []
24
33
  input_lines.each_with_index do |line, rowindex|
25
- row=[]
34
+ row = []
26
35
  line.split(' ').each_with_index do |word, colindex|
27
36
  flag = @connectors.include? word.downcase
28
37
 
29
38
  # if <word> is a conector and <pFilter>==true Then Choose this <word>
30
39
  # if <word> isn't a conector and <pFilter>==true and <word>.length>1 Then Choose this <word>
31
- if (flag and pFilter) || (!flag and !pFilter and word.length>1)
32
- output_words << {:word => word,
33
- :row => rowindex,
34
- :col => colindex }
40
+ if (flag and filter) || (!flag and !filter and word.length > 1)
41
+ output_words << {:word => word, :row => rowindex, :col => colindex }
35
42
  row << (output_words.size-1)
36
43
  else
37
44
  row << word
38
- end
45
+ end
39
46
  end
40
47
  row << '.'
41
48
  output_lines << row
42
- end
49
+ end
43
50
 
44
51
  indexes = []
45
- exclude = ['[', ']', '(', ')', "\"" ]
52
+ exclude = ['[', ']', '(', ')', '"']
46
53
  output_words.each_with_index do |item, index|
47
54
  flag = true
48
- exclude.each { |e| flag = false if (item[:word].include?(e)) }
55
+ exclude.each { |e| flag = false if item[:word].include? e }
49
56
  indexes << index if flag
50
57
  end
51
58
 
52
- result={ :lines => output_lines, :words => output_words, :indexes => indexes }
53
- return result
59
+ { lines: output_lines, words: output_words, indexes: indexes }
54
60
  end
55
61
 
62
+ ##
63
+ # Return text with connectors
56
64
  def text_with_connectors(text)
57
65
  text_filter_connectors(text, false)
58
66
  end
59
67
 
68
+ ##
69
+ # Return text without connectors
60
70
  def text_without_connectors(text)
61
- text_filter_connectors(text, true)
71
+ text_filter_connectors(text, true)
62
72
  end
63
73
 
64
- def build_text_from_filtered(pStruct, pIndexes)
65
- lines = pStruct[:lines]
66
- lIndexes = pIndexes.sort
67
- counter = 1
68
- lText = ''
74
+ def build_text_from_filtered(input_struct, input_indexes)
75
+ lines = input_struct[:lines]
76
+ indexes = input_indexes.sort
77
+ counter = 1
78
+ text = ''
69
79
 
70
80
  lines.each do |line|
71
81
  line.each do |value|
72
82
  if value.class == String
73
- lText += (' ' + value)
83
+ text += (' ' + value)
74
84
  elsif value == value.to_i
75
85
  # INFO: ruby 2.4 unifies Fixnum and Bignum into Integer
76
86
  # Avoid using deprecated classes.
77
- if lIndexes.include? value
78
- lText += " [#{counter.to_s}]"
87
+ if indexes.include? value
88
+ text += " [#{counter}]"
79
89
  counter += 1
80
90
  else
81
- lword = pStruct[:words][value][:word]
82
- lText += (' ' + lword)
91
+ word = input_struct[:words][value][:word]
92
+ text += (' ' + word)
83
93
  end
84
94
  end
85
95
  end
86
96
  end
87
- lText.gsub!(' .', '.')
88
- lText.gsub!(' ,', ',')
89
- lText = lText[1, lText.size] if lText[0] == ' '
90
- lText
97
+ text.gsub!(' .', '.')
98
+ text.gsub!(' ,', ',')
99
+ text = text[1, text.size] if text[0] == ' '
100
+ text
91
101
  end
92
102
 
93
- def count_words(pInputText)
94
- return 0 if pInputText.nil?
95
-
96
- t = pInputText.clone
97
- t.gsub!("\n"," ")
98
- t.gsub!("/"," ")
99
- #t.gsub!("-"," ")
100
- t.gsub!("."," ")
101
- t.gsub!(","," ")
102
- t.gsub!(" "," ")
103
- t.gsub!(" "," ")
104
- t.split(" ").count
103
+ ##
104
+ # Count words
105
+ # @param input (String)
106
+ # @return Integer
107
+ def count_words(input)
108
+ return 0 if input.nil?
109
+
110
+ t = input.clone
111
+ t.gsub!("\n", ' ')
112
+ t.gsub!('/', ' ')
113
+ # t.gsub!("-"," ")
114
+ t.gsub!('.', ' ')
115
+ t.gsub!(',', ' ')
116
+ t.gsub!(' ', ' ')
117
+ t.gsub!(' ', ' ')
118
+ t.split(' ').count
105
119
  end
106
120
 
107
- def do_mistake_to(pText = '')
108
- lText = pText.dup
121
+ ##
122
+ # Do mistake to input
123
+ # @param input (String)
124
+ # @return String
125
+ def do_mistake_to(input = '')
126
+ text = input.dup
109
127
  keys = @mistakes.keys
110
128
 
111
129
  # Try to do mistake with one item from the key list
112
130
  keys.shuffle!
113
131
  keys.each do |key|
114
- if lText.include? key.to_s
115
- values = @mistakes[key].split(',')
116
- values.shuffle!
117
- lText = lText.sub(key.to_s,values[0].to_s)
118
- return lText
119
- end
132
+ next unless text.include? key.to_s
133
+
134
+ values = @mistakes[key].split(',')
135
+ values.shuffle!
136
+ text = text.sub(key.to_s, values[0].to_s)
137
+ return text
120
138
  end
121
139
 
122
140
  # Force mistake by swapping letters
123
- if lText.size > 1
124
- i = rand(lText.size - 2)
125
- aux = lText[i]
126
- lText[i] = lText[i + 1]
127
- lText[i + 1] = aux
141
+ if text.size > 1
142
+ i = rand(text.size - 2)
143
+ aux = text[i]
144
+ text[i] = text[i + 1]
145
+ text[i + 1] = aux
128
146
  end
129
- return lText if lText != pText
147
+ return text if text != input
130
148
 
131
- lText + 's'
149
+ text + 's'
132
150
  end
133
151
 
134
152
  def hide_text(input_text)
@@ -3,7 +3,7 @@
3
3
  require 'rainbow'
4
4
  require 'rexml/document'
5
5
  require_relative '../logger'
6
- require_relative '../code/code'
6
+ require_relative '../data/code'
7
7
 
8
8
  # Read XML info about Code input data
9
9
  module CodeLoader
@@ -24,7 +24,7 @@ module CodeLoader
24
24
  # @param xmldata (XML Object)
25
25
  # @param filename (String) File name that contains data
26
26
  # @return Code object
27
- def self.read_codedata_from_xml(xmldata, filename)
27
+ private_class_method def self.read_codedata_from_xml(xmldata, filename)
28
28
  data = { path: '?', type: '?', features: [] }
29
29
  xmldata.elements.each do |i|
30
30
  data[:path] = i.text if i.name == 'path'
@@ -38,14 +38,14 @@ module CodeLoader
38
38
  # Read features data from XML input
39
39
  # @param xmldata (XML object)
40
40
  # @return Array with features (Strings)
41
- def self.read_features(xmldata, filename)
41
+ private_class_method def self.read_features(xmldata, filename)
42
42
  features = []
43
43
  xmldata.elements.each do |i|
44
44
  if i.name == 'row'
45
45
  features << i.text
46
46
  else
47
47
  msg = Rainbow("[ERROR] features/#{i.name} from #{filename}").color(:red)
48
- Logger.verbose msg
48
+ Logger.verboseln msg
49
49
  end
50
50
  end
51
51
  features
@@ -13,6 +13,8 @@ module ContentLoader
13
13
  # Load XML content into Asker data objects
14
14
  # @param filepath (String) File path
15
15
  # @param content (String) XML plane text content
16
+ # rubocop:disable Metrics/MethodLength
17
+ # rubocop:disable Metrics/AbcSize
16
18
  def self.load(filepath, content)
17
19
  concepts = []
18
20
  codes = []
@@ -37,11 +39,13 @@ module ContentLoader
37
39
 
38
40
  { concepts: concepts, codes: codes }
39
41
  end
42
+ # rubocop:enable Metrics/MethodLength
43
+ # rubocop:enable Metrics/AbcSize
40
44
 
41
45
  ##
42
46
  # Read lang attr from input XML data
43
47
  # @param xmldata (XML Object)
44
- def self.read_lang_attribute(xmldata)
48
+ private_class_method def self.read_lang_attribute(xmldata)
45
49
  begin
46
50
  lang = xmldata.root.attributes['lang']
47
51
  rescue StandardError
@@ -53,7 +57,7 @@ module ContentLoader
53
57
  ##
54
58
  # Read context attr from input XML data
55
59
  # @param xmldata (XML Object)
56
- def self.read_context_attribute(xmldata)
60
+ private_class_method def self.read_context_attribute(xmldata)
57
61
  begin
58
62
  context = xmldata.root.attributes['context']
59
63
  rescue StandardError
@@ -68,12 +72,10 @@ module ContentLoader
68
72
  # @param filepath (String)
69
73
  # @param lang
70
74
  # @param context
71
- def self.read_concept(xmldata, filepath, lang, context)
75
+ private_class_method def self.read_concept(xmldata, filepath, lang, context)
72
76
  project = Project.instance
73
77
  c = Concept.new(xmldata, filepath, lang, context)
74
- if [ File.basename(filepath), :default ].include? project.process_file
75
- c.process = true
76
- end
78
+ c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
77
79
  c
78
80
  end
79
81
 
@@ -81,18 +83,20 @@ module ContentLoader
81
83
  # Read code from input XML data
82
84
  # @param xmldata (XML Object)
83
85
  # @param filepath (String)
84
- def self.read_code(xmldata, filepath)
86
+ private_class_method def self.read_code(xmldata, filepath)
85
87
  project = Project.instance
86
88
  c = CodeLoader.load(xmldata, filepath)
87
- if [ File.basename(filepath), :default ].include? project.process_file
88
- c.process = true
89
- end
89
+ c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
90
90
  c
91
91
  end
92
92
 
93
- def self.raise_error_with(filepath, content)
93
+ ##
94
+ # Raise error and save content into error.file
95
+ # @param filepath (String)
96
+ # @param content (String)
97
+ private_class_method def self.raise_error_with(filepath, content)
94
98
  msg = Rainbow("[ERROR] ContentLoader: Format error in #{filepath}").red.bright
95
- Logger.verbose msg
99
+ Logger.verboseln msg
96
100
  f = File.open('output/error.xml', 'w')
97
101
  f.write(content)
98
102
  f.close
@@ -13,7 +13,7 @@ module DirectoryLoader
13
13
  files = (Dir.new(dirname).entries - ['.', '..']).sort
14
14
  # Accept only HAML or XML files
15
15
  accepted = files.select { |f| %w[.xml .haml].include? File.extname(f) }
16
- Logger.verbose " * Input directory = #{Rainbow(dirname).bright}"
16
+ Logger.verboseln " * Input directory = #{Rainbow(dirname).bright}"
17
17
  DirectoryLoader.load_files(accepted, dirname)
18
18
  end
19
19
 
@@ -49,9 +49,9 @@ module DirectoryLoader
49
49
  # @param last (Boolean) True if it is the last filename
50
50
  def self.load_file(filepath, last = false)
51
51
  if last
52
- Logger.verbose " └── Input file = #{Rainbow(filepath).bright}"
52
+ Logger.verboseln " └── Input file = #{Rainbow(filepath).bright}"
53
53
  else
54
- Logger.verbose " ├── Input file = #{Rainbow(filepath).bright}"
54
+ Logger.verboseln " ├── Input file = #{Rainbow(filepath).bright}"
55
55
  end
56
56
  FileLoader.load(filepath)
57
57
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ # Methods to load embedded files defined into asker input data file
6
+ # Example:
7
+ # * def line with :type = :image_url used to link external file as https://..."
8
+ # * def line with :type = :file used to load local file as image.png or file.txt"
9
+ module EmbeddedFile
10
+ ##
11
+ # @param value (String)
12
+ # @param localdir (String) Input file base folder
13
+ # @return Hash
14
+ # rubocop:disable Metrics/MethodLength
15
+ # rubocop:disable Metrics/AbcSize
16
+ def self.load(value, localdir)
17
+ # When filename is an URL
18
+ if value.start_with?('https://') || value.start_with?('http://')
19
+ return { text: "<img src=\"#{value}\" alt=\"image\" width=\"400\" height=\"300\">", file: :none }
20
+ end
21
+
22
+ filepath = File.join(localdir, value)
23
+ unless File.exist?(filepath)
24
+ # When filename is unkown!
25
+ Logger.verbose Rainbow("[ERROR] Unknown file! #{filepath}").red.bright
26
+ exit 1
27
+ end
28
+ # When filename is PNG, JPG o JPEG
29
+ if ['.png', '.jpg', '.jpeg'].include? File.extname(filepath)
30
+ # converts image into base64 strings
31
+ text = '<img src="@@PLUGINFILE@@/' + File.basename(filepath) \
32
+ + '" alt="imagen" class="img-responsive atto_image_button_text-bottom">'
33
+ data = '<file name="' + File.basename(filepath) + '" path="/" encoding="base64">' \
34
+ + Base64.strict_encode64(File.open(filepath, 'rb').read) + '</file>'
35
+ return { text: text, file: data }
36
+ end
37
+ # Suposse that filename is TXT file
38
+ return { text: "<pre>#{File.read(filepath)}</pre>", file: :none } if File.exist?(filepath)
39
+ end
40
+ # rubocop:enable Metrics/MethodLength
41
+ # rubocop:enable Metrics/AbcSize
42
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'haml'
4
3
  require_relative 'content_loader'
4
+ require_relative 'haml_loader'
5
5
  require_relative '../logger'
6
6
 
7
7
  # Methods that load a filename and return list of concepts
@@ -11,23 +11,14 @@ module FileLoader
11
11
  # @param filename (String) File name to be load
12
12
  def self.load(filename)
13
13
  if File.extname(filename).casecmp('.haml').zero?
14
- file_content = load_haml filename
14
+ file_content = HamlLoader.load filename
15
15
  elsif File.extname(filename).casecmp('.xml').zero?
16
16
  file_content = File.read(filename)
17
17
  else
18
18
  msg = "[ERROR] FileLoader: Format error #{filename}"
19
- Logger.verbose msg
19
+ Logger.verboseln msg
20
20
  raise msg
21
21
  end
22
22
  ContentLoader.load(filename, file_content)
23
23
  end
24
-
25
- ##
26
- # Load HAML file name
27
- # @param filename (String) HAML file name
28
- def self.load_haml(filename)
29
- template = File.read(filename)
30
- haml_engine = Haml::Engine.new(template)
31
- haml_engine.render
32
- end
33
24
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'haml'
4
+
5
+ # HAML file loader
6
+ module HamlLoader
7
+ ##
8
+ # Load HAML file name
9
+ # @param filename (String) HAML file name
10
+ def self.load(filename)
11
+ template = File.read(filename)
12
+ haml_engine = Haml::Engine.new(template)
13
+ haml_engine.render
14
+ end
15
+ end
@@ -1,8 +1,8 @@
1
1
 
2
2
  require 'net/http'
3
3
  require 'uri'
4
- require_relative '../project'
5
4
  require_relative '../application'
5
+ require_relative '../logger'
6
6
 
7
7
  # Search URL images on Internet
8
8
  # Methods:
@@ -12,9 +12,6 @@ require_relative '../application'
12
12
  module ImageUrlLoader
13
13
  # Search "input" images on Google and return URL
14
14
  def self.load(input = [])
15
- param = Application.instance.config['global']['internet'] || 'yes'
16
- return [] unless param == 'yes'
17
-
18
15
  filters = []
19
16
  if input.class == String
20
17
  filters += sanitize_string(input.clone)
@@ -39,20 +36,21 @@ module ImageUrlLoader
39
36
  end
40
37
  end
41
38
  rescue
42
- Project.instance.verboseln '[ERROR] ImageUrlLoader'
43
- Project.instance.verboseln " => #{search_url}"
44
- Project.instance.verboseln ' => Check Internet connections'
45
- Project.instance.verboseln ' => Ensure URL is well formed'
39
+ Logger.verboseln '[ERROR] ImageUrlLoader'
40
+ Logger.verboseln " => #{search_url}"
41
+ Logger.verboseln ' => Check Internet connections'
42
+ Logger.verboseln ' => Ensure URL is well formed'
46
43
  end
47
44
  image_urls
48
45
  end
49
46
 
50
47
  def self.sanitize_string(input)
48
+ text = input.dup
51
49
  r = [ ['á', 'a'], ['é', 'e'], ['í', 'i'], ['ó', 'o'], ['ú', 'u'], ['ñ', 'n'], ['Á', 'A'], ['É', 'E'], ['Í', 'I'], ['Ó', 'O'], ['Ú', 'U'], ['Ñ', 'N']]
52
- r.each { |item| input.gsub!(item[0], item[1]) }
50
+ r.each { |item| text.gsub!(item[0], item[1]) }
53
51
  r = ['-', '_', ',', '"']
54
- r.each { |item| input.gsub!(item, ' ') }
55
- input.split(' ')
52
+ r.each { |item| text.gsub!(item, ' ') }
53
+ text.split(' ')
56
54
  end
57
55
 
58
56
  def self.sanitize_array(input)
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'directory_loader'
4
+ require_relative '../ai/concept_ai'
5
+ require_relative '../data/world'
4
6
  require_relative '../logger'
5
7
 
6
8
  # Load DATA defined into our Project
@@ -9,16 +11,30 @@ module InputLoader
9
11
  # Load input data from every input directory
10
12
  # @param inputdirs (Array)
11
13
  def self.load(inputdirs)
12
- output = { concepts: [], codes: [] }
13
- Logger.verbose "\n[INFO] Loading input data"
14
-
15
- # inputdirs = project.inputdirs.split(',')
14
+ data = { concepts: [], codes: [], world: nil,
15
+ concepts_ai: [], codes_ai: [] }
16
+ Logger.verboseln "\n[INFO] Loading input data"
16
17
  inputdirs.each do |dirname|
17
- data = DirectoryLoader.load(dirname)
18
- output[:concepts] += data[:concepts]
19
- output[:codes] += data[:codes]
18
+ temp = DirectoryLoader.load(dirname)
19
+ data[:concepts] += temp[:concepts]
20
+ data[:codes] += temp[:codes]
20
21
  end
22
+ create_questions(data)
23
+ end
21
24
 
22
- output
25
+ private_class_method def self.create_questions(data)
26
+ # Create World data
27
+ # * Calculate concept neighbours
28
+ # * TO-DO: Calculate code neighbours
29
+ data[:world] = World.new(data[:concepts])
30
+ # Create ConceptAI data (ConceptAI = concept + questions)
31
+ data[:concepts].each do |concept|
32
+ data[:concepts_ai] << ConceptAI.new(concept, data[:world])
33
+ end
34
+ # Create CodeAI data (CodeAI = code + questions)
35
+ data[:codes].each do |code|
36
+ data[:codes_ai] << CodeAIFactory.get(code)
37
+ end
38
+ data
23
39
  end
24
40
  end