asker-tool 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +53 -0
  4. data/bin/asker +4 -0
  5. data/docs/changelog/v2.1.md +99 -0
  6. data/docs/commands.md +15 -0
  7. data/docs/contributions.md +18 -0
  8. data/docs/history.md +40 -0
  9. data/docs/idea.md +44 -0
  10. data/docs/inputs/README.md +39 -0
  11. data/docs/inputs/code.md +69 -0
  12. data/docs/inputs/concepts.md +142 -0
  13. data/docs/inputs/jedi.md +68 -0
  14. data/docs/inputs/tables.md +112 -0
  15. data/docs/inputs/templates.md +87 -0
  16. data/docs/install/README.md +38 -0
  17. data/docs/install/manual.md +26 -0
  18. data/docs/install/scripts.md +26 -0
  19. data/docs/revise/asker-file.md +41 -0
  20. data/docs/revise/buenas-practicas/01-convocatoria.md +30 -0
  21. data/docs/revise/buenas-practicas/02-formulario.md +35 -0
  22. data/docs/revise/buenas-practicas/03-descripcion.md +63 -0
  23. data/docs/revise/buenas-practicas/04-resultados.md +17 -0
  24. data/docs/revise/buenas-practicas/05-reproducir.md +10 -0
  25. data/docs/revise/ejemplos/01/README.md +27 -0
  26. data/docs/revise/ejemplos/02/README.md +31 -0
  27. data/docs/revise/ejemplos/03/README.md +31 -0
  28. data/docs/revise/ejemplos/04/README.md +37 -0
  29. data/docs/revise/ejemplos/05/README.md +25 -0
  30. data/docs/revise/ejemplos/06/README.md +43 -0
  31. data/docs/revise/ejemplos/README.md +11 -0
  32. data/docs/revise/projects.md +74 -0
  33. data/lib/asker.rb +103 -0
  34. data/lib/asker/ai/ai.rb +70 -0
  35. data/lib/asker/ai/ai_calculate.rb +55 -0
  36. data/lib/asker/ai/concept_ai.rb +49 -0
  37. data/lib/asker/ai/question.rb +58 -0
  38. data/lib/asker/ai/stages/base_stage.rb +16 -0
  39. data/lib/asker/ai/stages/main.rb +8 -0
  40. data/lib/asker/ai/stages/stage_b.rb +87 -0
  41. data/lib/asker/ai/stages/stage_d.rb +160 -0
  42. data/lib/asker/ai/stages/stage_f.rb +156 -0
  43. data/lib/asker/ai/stages/stage_i.rb +140 -0
  44. data/lib/asker/ai/stages/stage_s.rb +52 -0
  45. data/lib/asker/ai/stages/stage_t.rb +170 -0
  46. data/lib/asker/application.rb +30 -0
  47. data/lib/asker/checker.rb +356 -0
  48. data/lib/asker/cli.rb +85 -0
  49. data/lib/asker/code/ai/base_code_ai.rb +48 -0
  50. data/lib/asker/code/ai/code_ai_factory.rb +26 -0
  51. data/lib/asker/code/ai/javascript_code_ai.rb +167 -0
  52. data/lib/asker/code/ai/python_code_ai.rb +167 -0
  53. data/lib/asker/code/ai/ruby_code_ai.rb +169 -0
  54. data/lib/asker/code/ai/sql_code_ai.rb +69 -0
  55. data/lib/asker/code/code.rb +53 -0
  56. data/lib/asker/data/column.rb +62 -0
  57. data/lib/asker/data/concept.rb +183 -0
  58. data/lib/asker/data/data_field.rb +87 -0
  59. data/lib/asker/data/row.rb +93 -0
  60. data/lib/asker/data/table.rb +96 -0
  61. data/lib/asker/data/template.rb +65 -0
  62. data/lib/asker/data/world.rb +53 -0
  63. data/lib/asker/exporter/code_gift_exporter.rb +35 -0
  64. data/lib/asker/exporter/code_screen_exporter.rb +45 -0
  65. data/lib/asker/exporter/concept_ai_gift_exporter.rb +33 -0
  66. data/lib/asker/exporter/concept_ai_screen_exporter.rb +115 -0
  67. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +33 -0
  68. data/lib/asker/exporter/concept_doc_exporter.rb +21 -0
  69. data/lib/asker/exporter/concept_screen_exporter.rb +25 -0
  70. data/lib/asker/exporter/main.rb +9 -0
  71. data/lib/asker/files/config.ini +40 -0
  72. data/lib/asker/formatter/code_string_formatter.rb +16 -0
  73. data/lib/asker/formatter/concept_doc_formatter.rb +37 -0
  74. data/lib/asker/formatter/concept_string_formatter.rb +66 -0
  75. data/lib/asker/formatter/question_gift_formatter.rb +65 -0
  76. data/lib/asker/formatter/question_hash_formatter.rb +40 -0
  77. data/lib/asker/formatter/question_moodlexml_formatter.rb +71 -0
  78. data/lib/asker/formatter/rb2haml_formatter.rb +26 -0
  79. data/lib/asker/lang/lang.rb +42 -0
  80. data/lib/asker/lang/lang_factory.rb +19 -0
  81. data/lib/asker/lang/text_actions.rb +150 -0
  82. data/lib/asker/loader/code_loader.rb +53 -0
  83. data/lib/asker/loader/content_loader.rb +101 -0
  84. data/lib/asker/loader/directory_loader.rb +58 -0
  85. data/lib/asker/loader/file_loader.rb +33 -0
  86. data/lib/asker/loader/image_url_loader.rb +61 -0
  87. data/lib/asker/loader/input_loader.rb +24 -0
  88. data/lib/asker/loader/project_loader.rb +71 -0
  89. data/lib/asker/logger.rb +21 -0
  90. data/lib/asker/project.rb +170 -0
  91. metadata +261 -0
@@ -0,0 +1,69 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+ require_relative 'base_code_ai'
5
+
6
+ class SQLCodeAI < BaseCodeAI
7
+ def initialize(data_object)
8
+ @data_object = data_object
9
+ @lines = data_object.lines
10
+ @lang = LangFactory.instance.get('sql')
11
+ @num = 0
12
+ @questions = []
13
+ end
14
+
15
+ def make_comment_error
16
+ error_lines = []
17
+ questions = []
18
+ @lines.each_with_index do |line,index|
19
+ if line.include?('//')
20
+ lines = clone_array @lines
21
+ lines[index].sub!('//','').strip!
22
+
23
+ q = Question.new(:short)
24
+ q.name = "#{name}-#{num}-code1uncomment"
25
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
26
+ q.shorts << (index+1)
27
+ q.feedback = 'Comment symbol removed'
28
+ questions << q
29
+ elsif line.strip.size>0
30
+ lines = clone_array @lines
31
+ lines[index]='// ' + lines[index]
32
+
33
+ q = Question.new(:short)
34
+ q.name = "#{name}-#{num}-code1comment"
35
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
36
+ q.shorts << (index+1)
37
+ q.feedback = 'Comment symbol added'
38
+ questions << q
39
+ end
40
+ end
41
+ questions
42
+ end
43
+
44
+ def make_keyword_error
45
+ error_lines = []
46
+ questions = []
47
+
48
+ @lang.mistakes.each_pair do |key,values|
49
+ v = values.split(',')
50
+ v.each do |value|
51
+ @lines.each_with_index do |line,index|
52
+ error_lines << index if line.include?(key.to_s)
53
+ end
54
+
55
+ error_lines.each do |index|
56
+ lines = clone_array @lines
57
+ lines[index].sub!(key.to_s, value)
58
+ q = Question.new(:short)
59
+ q.name = "#{name}-#{num}-code1keyword"
60
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
61
+ q.shorts << (index+1)
62
+ q.feedback = "Keyword error: '#{value}' must be '#{key}'"
63
+ questions << q
64
+ end
65
+ end
66
+ end
67
+ questions
68
+ end
69
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'ai/code_ai_factory'
2
+ require_relative '../project'
3
+ require_relative '../formatter/code_string_formatter'
4
+
5
+ # Contains code data input
6
+ class Code
7
+ attr_reader :dirname, :filename, :type
8
+ attr_accessor :process, :features
9
+ attr_reader :lines, :questions
10
+
11
+ def initialize(dirname, filename, type)
12
+ @dirname = dirname
13
+ @filename = filename
14
+ @type = type
15
+ @filepath = File.join(@dirname, @filename)
16
+ @process = false
17
+ @features = []
18
+ @lines = load(@filepath)
19
+ @questions = []
20
+ @code_ai = CodeAIFactory.get(self)
21
+ end
22
+
23
+ def process?
24
+ @process
25
+ end
26
+
27
+ def make_questions
28
+ return unless process?
29
+ @questions += @code_ai.make_questions
30
+ end
31
+
32
+ def lines_to_s(lines)
33
+ out = ''
34
+ lines.each_with_index do |line, index|
35
+ out << format("%2d| #{line}\n", (index + 1))
36
+ end
37
+ out
38
+ end
39
+
40
+ def debug
41
+ out = CodeStringFormatter.to_s(self)
42
+ p = Project.instance
43
+ p.verbose out
44
+ end
45
+
46
+ private
47
+
48
+ def load(filepath)
49
+ return if filepath.nil?
50
+ content = File.read(filepath)
51
+ content.split("\n")
52
+ end
53
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Contain data information for every column
5
+ # Params:
6
+ # * +pRow+ - Parent row for this column
7
+ # * +index+ - Sequence order (Integer)
8
+ # * +xml_data+ - XML input data
9
+ class Column
10
+ attr_reader :row, :index, :id, :raw, :lang, :type, :simple
11
+
12
+ def initialize(row, index, xml_data)
13
+ @row = row
14
+ @index = index
15
+ @id = @row.id + '.' + @index.to_s
16
+ @raw = ''
17
+ @lang = @row.langs[@index]
18
+ @type = @row.types[@index]
19
+ @simple = { lang: true, type: true }
20
+ read_data_from_xml(xml_data)
21
+ end
22
+
23
+ def to_html
24
+ case @type
25
+ when 'text'
26
+ return @raw
27
+ when 'image_url'
28
+ return "<img src=\"#{raw}\" alt\=\"image\">"
29
+ when 'textfile_path'
30
+ return "<pre>#{raw}</pre>"
31
+ else
32
+ return "ERROR type #{@type}"
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def read_data_from_xml(xml_data)
39
+ raise '[ERROR] Column XML data with elements!' if xml_data.elements.count.positive?
40
+
41
+ @raw = xml_data.text.strip.to_s
42
+
43
+ # read attributes from XML input data
44
+ if xml_data.attributes['lang']
45
+ code = xml_data.attributes['lang'].strip
46
+ if code != @lang.code
47
+ @lang = LangFactory.instance.get(code)
48
+ @simple[:lang] = false
49
+ @row.simple_off(:lang)
50
+ end
51
+ end
52
+
53
+ if xml_data.attributes['type']
54
+ type = xml_data.attributes['type'].strip
55
+ if type != @type.to_s
56
+ @type = type
57
+ @simple[:type] = false
58
+ @row.simple_off(:type)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+ require 'rexml/document'
5
+
6
+ require_relative '../project'
7
+ require_relative '../lang/lang_factory'
8
+ require_relative 'table'
9
+ require_relative 'data_field'
10
+
11
+ # Store Concept information
12
+ 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
+
20
+ def initialize(xml_data, filename, lang_code = 'en', context = [])
21
+ @@id += 1
22
+ @id = @@id
23
+
24
+ @filename = filename
25
+ @process = false
26
+ @lang = LangFactory.instance.get(lang_code)
27
+
28
+ if context.class == Array
29
+ @context = context
30
+ elsif context.nil?
31
+ @context = []
32
+ else
33
+ @context = context.split(',')
34
+ @context.collect!(&:strip)
35
+ end
36
+ @names = ['concept.' + @id.to_s]
37
+ @type = 'text'
38
+
39
+ @data = {}
40
+ @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
44
+ @data[:tables] = []
45
+ @data[:neighbors] = []
46
+ @data[:reference_to] = []
47
+ @data[:referenced_by] = []
48
+
49
+ read_data_from_xml(xml_data)
50
+ end
51
+
52
+ def name(option = :raw)
53
+ DataField.new(@names[0], @id, @type).get(option)
54
+ end
55
+
56
+ def text
57
+ @data[:texts][0] || '...'
58
+ end
59
+
60
+ def process?
61
+ @process
62
+ end
63
+
64
+ def try_adding_neighbor(other)
65
+ p = calculate_nearness_to_concept(other)
66
+ return if p.zero?
67
+
68
+ @data[:neighbors] << { concept: other, value: p }
69
+ # Sort neighbors list
70
+ @data[:neighbors].sort! { |a, b| a[:value] <=> b[:value] }
71
+ @data[:neighbors].reverse!
72
+ end
73
+
74
+ def calculate_nearness_to_concept(other)
75
+ weights = Project.instance.formula_weights
76
+
77
+ li_max1 = @context.count
78
+ li_max2 = @data[:tags].count
79
+ li_max3 = @data[:tables].count
80
+
81
+ lf_alike1 = lf_alike2 = lf_alike3 = 0.0
82
+
83
+ # 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? }
87
+
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)
91
+ end
92
+
93
+ def try_adding_references(other)
94
+ reference_to = 0
95
+ @data[:tags].each { |i| reference_to += 1 unless other.names.index(i.downcase).nil? }
96
+ @data[:texts].each do |t|
97
+ text = t.clone
98
+ text.split(' ').each do |word|
99
+ reference_to += 1 unless other.names.index(word.downcase).nil?
100
+ end
101
+ end
102
+ if reference_to.positive?
103
+ @data[:reference_to] << other.name
104
+ other.data[:referenced_by] << name
105
+ end
106
+ end
107
+
108
+ def method_missing(method)
109
+ @data[method]
110
+ end
111
+
112
+ private
113
+
114
+ def read_data_from_xml(xml_data)
115
+ xml_data.elements.each do |i|
116
+ case i.name
117
+ when 'names'
118
+ process_names(i)
119
+ when 'tags'
120
+ 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
+ when 'def'
129
+ process_def(i)
130
+ when 'table'
131
+ @data[:tables] << Table.new(self, i)
132
+ else
133
+ text = " [ERROR] <#{i.name}> unkown XML attribute for concept #{name}"
134
+ msg = Rainbow(text).color(:red)
135
+ Project.instance.verbose msg
136
+ end
137
+ end
138
+ end
139
+
140
+ def process_names(value)
141
+ @names = []
142
+ j = value.text.split(',')
143
+ j.each { |k| @names << k.strip }
144
+ @type = value.attributes['type'].strip if value.attributes['type']
145
+ end
146
+
147
+ def process_tags(value)
148
+ raise '[Error] tags label empty!' if value.text.nil? || value.text.size.zero?
149
+ @data[:tags] = value.text.split(',')
150
+ @data[:tags].collect!(&:strip)
151
+ end
152
+
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
+
170
+ def process_def(value)
171
+ 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
+ when 'image_url'
176
+ @data[:images] << value.text.strip
177
+ when 'textfile_path'
178
+ @data[:textfile_paths] << value.text.strip
179
+ else
180
+ @data[:texts] << value.text.strip
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Contain data information for every field
4
+ # Params:
5
+ # * +data+ - Data (Text). This is the field content
6
+ # * +id+ - Identifier (Integer)
7
+ # * +type+ - May be "text", "textfile_path", "textfile_url" or "image_url"
8
+ class DataField
9
+ attr_reader :id, :type
10
+
11
+ def initialize(data, id, type)
12
+ @data = data
13
+ @id = id.to_i # TODO: revise where it comes from? Is it unique value?
14
+ @type = type.to_sym
15
+ end
16
+
17
+ def get(option = :raw)
18
+ case @type
19
+ when :text
20
+ return get_text(option)
21
+ when :textfile_path
22
+ return get_textfile_path(option)
23
+ when :textfile_url
24
+ return get_textfile_url(option)
25
+ when :image_url
26
+ return get_image_url(option)
27
+ end
28
+ raise ".get: data=#{@data}, type=#{@type}, option=#{option}"
29
+ end
30
+
31
+ private
32
+
33
+ def get_text(option)
34
+ return to_screen(@data) if option == :screen
35
+
36
+ @data
37
+ end
38
+
39
+ def get_textfile_path(option)
40
+ case option
41
+ when :raw
42
+ return @data
43
+ when :id
44
+ return "textfile_path.#{@id}"
45
+ when :decorated
46
+ content = File.new(@data).read
47
+ return "<pre>\n#{content}</pre>"
48
+ when :screen
49
+ return to_screen(@data)
50
+ end
51
+ raise ".get_textfile_path: data=#{@data}, type=#{@type}, option=#{option}"
52
+ end
53
+
54
+ def get_textfile_url(option)
55
+ case option
56
+ when :raw
57
+ return @data
58
+ when :id
59
+ return "textfile_url.#{@id}"
60
+ when :decorated
61
+ return "<a href=\"#{@data}\">Textfile URL</a>"
62
+ when :screen
63
+ return to_screen(@data)
64
+ end
65
+ raise ".get_textfile_url: data=#{@data}, type=#{@type}, option=#{option}"
66
+ end
67
+
68
+ def get_image_url(option)
69
+ case option
70
+ when :raw
71
+ return @data
72
+ when :id
73
+ return "image_url.#{@id}"
74
+ when :decorated
75
+ return "<img src=\"#{@data}\" alt=\"image\">"
76
+ when :screen
77
+ return to_screen(@data)
78
+ end
79
+ raise ".get_image_url: data=#{@data}, type=#{@type}, option=#{option}"
80
+ end
81
+
82
+ def to_screen(text)
83
+ return text[0, 7] + '...' + text[-15, 15] if text.size > 25
84
+
85
+ text
86
+ end
87
+ end