asker-tool 2.1.5 → 2.1.6

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE → LICENSE.txt} +0 -0
  3. data/README.md +2 -3
  4. data/bin/asker +1 -0
  5. data/lib/asker.rb +10 -6
  6. data/lib/asker/ai/ai.rb +4 -0
  7. data/lib/asker/ai/code/base_code_ai.rb +104 -0
  8. data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
  9. data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
  10. data/lib/asker/ai/code/problem_code_ai.rb +176 -0
  11. data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
  12. data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
  13. data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
  14. data/lib/asker/ai/concept_ai.rb +1 -0
  15. data/lib/asker/ai/stages/stage_t.rb +76 -76
  16. data/lib/asker/application.rb +18 -2
  17. data/lib/asker/checker.rb +112 -30
  18. data/lib/asker/cli.rb +12 -25
  19. data/lib/asker/data/code.rb +73 -0
  20. data/lib/asker/data/column.rb +31 -21
  21. data/lib/asker/data/concept.rb +42 -45
  22. data/lib/asker/data/data_field.rb +14 -0
  23. data/lib/asker/data/row.rb +75 -52
  24. data/lib/asker/data/table.rb +89 -42
  25. data/lib/asker/data/world.rb +57 -33
  26. data/lib/asker/displayer/concept_ai_displayer.rb +56 -37
  27. data/lib/asker/displayer/concept_displayer.rb +7 -5
  28. data/lib/asker/displayer/stats_displayer.rb +4 -3
  29. data/lib/asker/exporter/concept_ai_gift_exporter.rb +5 -3
  30. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -3
  31. data/lib/asker/exporter/output_file_exporter.rb +1 -1
  32. data/lib/asker/files/config.ini +37 -0
  33. data/lib/asker/files/example-concept.haml +0 -1
  34. data/lib/asker/{lang/locales → files/language}/du/templates.yaml +0 -0
  35. data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
  36. data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
  37. data/lib/asker/{lang/locales → files/language}/en/templates.yaml +0 -0
  38. data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
  39. data/lib/asker/{lang/locales → files/language}/es/mistakes.yaml +0 -0
  40. data/lib/asker/{lang/locales → files/language}/es/templates.yaml +0 -0
  41. data/lib/asker/{lang/locales → files/language}/fr/connectors.yaml +0 -0
  42. data/lib/asker/{lang/locales → files/language}/fr/mistakes.yaml +0 -0
  43. data/lib/asker/{lang/locales → files/language}/fr/templates.yaml +0 -0
  44. data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
  45. data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
  46. data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
  47. data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
  48. data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
  49. data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
  50. data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
  51. data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
  52. data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
  53. data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
  54. data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
  55. data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
  56. data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
  57. data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
  58. data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
  59. data/lib/asker/lang/lang.rb +17 -10
  60. data/lib/asker/lang/lang_factory.rb +26 -5
  61. data/lib/asker/lang/text_actions.rb +87 -69
  62. data/lib/asker/loader/code_loader.rb +3 -3
  63. data/lib/asker/loader/content_loader.rb +9 -5
  64. data/lib/asker/loader/file_loader.rb +2 -11
  65. data/lib/asker/loader/haml_loader.rb +15 -0
  66. data/lib/asker/loader/image_url_loader.rb +5 -8
  67. data/lib/asker/loader/input_loader.rb +8 -9
  68. data/lib/asker/loader/project_loader.rb +10 -8
  69. data/lib/asker/logger.rb +3 -3
  70. data/lib/asker/project.rb +24 -50
  71. data/lib/asker/skeleton.rb +22 -13
  72. metadata +39 -37
  73. data/lib/asker/code/ai/base_code_ai.rb +0 -48
  74. data/lib/asker/code/code.rb +0 -53
data/lib/asker/cli.rb CHANGED
@@ -21,7 +21,6 @@ class CLI < Thor
21
21
 
22
22
  map ['f', '-f', '--file'] => 'file'
23
23
  desc 'file NAME', 'Build output files, from HAML/XML input file.'
24
- option :color, type: :boolean
25
24
  long_desc <<-LONGDESC
26
25
  Create output files, from input file (HAML/XML format).
27
26
 
@@ -33,36 +32,17 @@ class CLI < Thor
33
32
 
34
33
  (2) #{Rainbow('asker input/foo/foo.xml').yellow}, Build questions from XML file.
35
34
 
36
- (3) #{Rainbow('asker file --no-color input/foo/foo.haml').yellow}, Same as (1) but without colors.
37
-
38
- (4) #{Rainbow('asker projects/foo/foo.yaml').yellow}, Build questions from YAML project file.
35
+ (3) #{Rainbow('asker projects/foo/foo.yaml').yellow}, Build questions from YAML project file.
39
36
 
40
37
  LONGDESC
41
38
  ##
42
39
  # Create questions from input file
43
40
  # @param filename (String) Path to input file
44
41
  def file(filename)
45
- # Enable/disable color output
46
- Rainbow.enabled = false if options['color'] == false
47
42
  # Asker start processing input file
48
43
  Asker.start(filename)
49
44
  end
50
45
 
51
- map ['i', '-i', '--init'] => 'init'
52
- desc 'init', 'Create default INI config fie'
53
- ##
54
- # Create default INI config file
55
- def init
56
- src = File.join(File.dirname(__FILE__), 'files', 'config.ini')
57
- dst = File.join(Dir.pwd, 'config.ini')
58
- if File.exist? dst
59
- puts "[WARN] Exists file! => #{Rainbow(File.basename(dst)).yellow.bright}"
60
- else
61
- FileUtils.cp(src, dst)
62
- puts "[ OK ] Create file => #{Rainbow(File.basename(dst)).green}"
63
- end
64
- end
65
-
66
46
  map ['c', '-c', '--check'] => 'check'
67
47
  desc 'check', 'Check input HAML file syntax'
68
48
  ##
@@ -75,14 +55,21 @@ class CLI < Thor
75
55
  Asker.check(filename)
76
56
  end
77
57
 
78
- map ['n', '-b', '--new', 'new'] => 'create_skeleton'
58
+ map ['i', '-i', '--init'] => 'init'
59
+ desc 'init', 'Create default INI config fie'
60
+ ##
61
+ # Create default INI config file
62
+ def init
63
+ Asker.create_configuration
64
+ end
65
+
66
+ map ['n', '-b', '--new', 'new'] => 'create_input'
79
67
  desc 'new', 'Create Asker demo input files'
80
68
  ##
81
69
  # Create Asker demo input files
82
70
  # @param dirname (String) Path to folder
83
- def create_skeleton(dirname)
84
- # Asker start processing input file
85
- Asker.create_skeleton(dirname)
71
+ def create_input(dirname)
72
+ Asker.create_input(dirname)
86
73
  end
87
74
 
88
75
  ##
@@ -0,0 +1,73 @@
1
+ require_relative '../ai/code/code_ai_factory'
2
+ require_relative '../project'
3
+ require_relative '../logger'
4
+ require_relative '../formatter/code_string_formatter'
5
+
6
+ ##
7
+ # Code data object
8
+ class Code
9
+ attr_reader :dirname, :filename, :type
10
+ attr_accessor :process, :features
11
+ attr_reader :lines, :questions
12
+
13
+ ##
14
+ # Initialize Code object
15
+ # @param dirname (String)
16
+ # @param filename (String)
17
+ # @param type (String)
18
+ def initialize(dirname, filename, type)
19
+ @dirname = dirname
20
+ @filename = filename
21
+ @type = type
22
+ @filepath = File.join(@dirname, @filename)
23
+ @process = false
24
+ @features = []
25
+ @lines = load(@filepath)
26
+ @questions = []
27
+ end
28
+
29
+ def process?
30
+ @process
31
+ end
32
+
33
+ def lines_to_s(lines)
34
+ out = ''
35
+ lines.each_with_index do |line, index|
36
+ out << format("%2d| #{line}\n", (index + 1))
37
+ end
38
+ out
39
+ end
40
+
41
+ def debug
42
+ Logger.verbose CodeStringFormatter.to_s(self)
43
+ end
44
+
45
+ private
46
+
47
+ def load(filepath)
48
+ return if filepath.nil?
49
+ unless File.exist? filepath
50
+ Logger.verboseln Rainbow("[ERROR] Unkown file #{filepath}").red.bright
51
+ return
52
+ end
53
+ content = File.read(filepath)
54
+ encode_and_split(content)
55
+ end
56
+
57
+ def encode_and_split(text, encoding = :default)
58
+ # Convert text to UTF-8 deleting unknown chars
59
+ text = text || '' # Ensure text is not nil
60
+ flag = [:default, 'UTF-8'].include? encoding
61
+ return text.encode('UTF-8', invalid: :replace).split("\n") if flag
62
+
63
+ # Convert text from input ENCODING to UTF-8
64
+ ec = Encoding::Converter.new(encoding.to_s, 'UTF-8')
65
+ begin
66
+ text = ec.convert(text)
67
+ rescue StandardError => e
68
+ puts "[ERROR] Encoding: #{e}"
69
+ end
70
+
71
+ text.split("\n")
72
+ end
73
+ end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # encoding: utf-8
3
2
 
4
3
  # Contain data information for every column
5
4
  # Params:
@@ -9,10 +8,15 @@
9
8
  class Column
10
9
  attr_reader :row, :index, :id, :raw, :lang, :type, :simple
11
10
 
11
+ ##
12
+ # initialize Column
13
+ # @param row (Row)
14
+ # @param index (Integer)
15
+ # @param xml_data (XMLdata)
12
16
  def initialize(row, index, xml_data)
13
17
  @row = row
14
18
  @index = index
15
- @id = @row.id + '.' + @index.to_s
19
+ @id = "#{@row.id}.#{@index}"
16
20
  @raw = ''
17
21
  @lang = @row.langs[@index]
18
22
  @type = @row.types[@index]
@@ -28,35 +32,41 @@ class Column
28
32
  return "<img src=\"#{raw}\" alt\=\"image\">"
29
33
  when 'textfile_path'
30
34
  return "<pre>#{raw}</pre>"
31
- else
32
- return "ERROR type #{@type}"
33
35
  end
36
+ "ERROR type #{@type}"
34
37
  end
35
38
 
36
39
  private
37
40
 
38
41
  def read_data_from_xml(xml_data)
39
- raise '[ERROR] Column XML data with elements!' if xml_data.elements.count.positive?
42
+ raise '[ERROR] Column with elements!' if xml_data.elements.count.positive?
40
43
 
41
44
  @raw = xml_data.text.strip.to_s
42
45
 
43
46
  # 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
47
+ read_lang_from_xml(xml_data)
48
+ read_type_from_xml(xml_data)
49
+ end
52
50
 
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
51
+ def read_lang_from_xml(xml_data)
52
+ return unless xml_data.attributes['lang']
53
+
54
+ code = xml_data.attributes['lang'].strip
55
+ return if code == @lang.code
56
+
57
+ @lang = LangFactory.instance.get(code)
58
+ @simple[:lang] = false
59
+ @row.simple_off(:lang)
60
+ end
61
+
62
+ def read_type_from_xml(xml_data)
63
+ return unless xml_data.attributes['type']
64
+
65
+ type = xml_data.attributes['type'].strip
66
+ return if type == @type.to_s
67
+
68
+ @type = type
69
+ @simple[:type] = false
70
+ @row.simple_off(:type)
61
71
  end
62
72
  end
@@ -3,11 +3,13 @@
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'
8
9
  require_relative 'table'
9
10
  require_relative 'data_field'
10
11
 
12
+ ##
11
13
  # Store Concept information
12
14
  class Concept
13
15
  attr_reader :id, :lang, :context
@@ -15,8 +17,14 @@ class Concept
15
17
  attr_reader :data
16
18
  attr_accessor :process
17
19
 
18
- @@id = 0
20
+ @@id = 0 # Concept counter
19
21
 
22
+ ##
23
+ # Initilize Concept
24
+ # @param xml_data (XML)
25
+ # @param filename (String)
26
+ # @param lang_code (String)
27
+ # @param context (Array)
20
28
  def initialize(xml_data, filename, lang_code = 'en', context = [])
21
29
  @@id += 1
22
30
  @id = @@id
@@ -72,38 +80,43 @@ class Concept
72
80
  end
73
81
 
74
82
  def calculate_nearness_to_concept(other)
75
- weights = Project.instance.formula_weights
83
+ a = Application.instance.config['ai']['formula_weights']
84
+ weights = a.split(',').map(&:to_f)
76
85
 
77
- li_max1 = @context.count
78
- li_max2 = @data[:tags].count
79
- li_max3 = @data[:tables].count
86
+ max1 = @context.count
87
+ max2 = @data[:tags].count
88
+ max3 = @data[:tables].count
80
89
 
81
- lf_alike1 = lf_alike2 = lf_alike3 = 0.0
90
+ alike1 = alike2 = alike3 = 0.0
82
91
 
83
92
  # 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? }
93
+ @context.each { |i| alike1 += 1.0 unless other.context.index(i).nil? }
94
+ @data[:tags].each { |i| alike2 += 1.0 unless other.tags.index(i).nil? }
95
+ @data[:tables].each { |i| alike3 += 1.0 unless other.tables.index(i).nil? }
87
96
 
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)
97
+ alike = (alike1 * weights[0] + alike2 * weights[1] + alike3 * weights[2])
98
+ max = (max1 * weights[0] + max2 * weights[1] + max3 * weights[2])
99
+ (alike * 100.0 / max)
91
100
  end
92
101
 
102
+ # rubocop:disable Metrics/MethodLength
93
103
  def try_adding_references(other)
94
104
  reference_to = 0
95
- @data[:tags].each { |i| reference_to += 1 unless other.names.index(i.downcase).nil? }
105
+ @data[:tags].each do |i|
106
+ reference_to += 1 unless other.names.index(i.downcase).nil?
107
+ end
96
108
  @data[:texts].each do |t|
97
109
  text = t.clone
98
110
  text.split(' ').each do |word|
99
111
  reference_to += 1 unless other.names.index(word.downcase).nil?
100
112
  end
101
113
  end
102
- if reference_to.positive?
103
- @data[:reference_to] << other.name
104
- other.data[:referenced_by] << name
105
- end
114
+ return unless reference_to.positive?
115
+
116
+ @data[:reference_to] << other.name
117
+ other.data[:referenced_by] << name
106
118
  end
119
+ # rubocop:enable Metrics/MethodLength
107
120
 
108
121
  def method_missing(method)
109
122
  @data[method]
@@ -111,6 +124,7 @@ class Concept
111
124
 
112
125
  private
113
126
 
127
+ # rubocop:disable Metrics/MethodLength
114
128
  def read_data_from_xml(xml_data)
115
129
  xml_data.elements.each do |i|
116
130
  case i.name
@@ -118,24 +132,17 @@ class Concept
118
132
  process_names(i)
119
133
  when 'tags'
120
134
  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
135
  when 'def'
129
136
  process_def(i)
130
137
  when 'table'
131
138
  @data[:tables] << Table.new(self, i)
132
139
  else
133
140
  text = " [ERROR] <#{i.name}> unkown XML attribute for concept #{name}"
134
- msg = Rainbow(text).color(:red)
135
- Project.instance.verbose msg
141
+ Logger.verbose Rainbow(text).color(:red)
136
142
  end
137
143
  end
138
144
  end
145
+ # rubocop:enable Metrics/MethodLength
139
146
 
140
147
  def process_names(value)
141
148
  @names = []
@@ -145,28 +152,16 @@ class Concept
145
152
  end
146
153
 
147
154
  def process_tags(value)
148
- raise '[Error] tags label empty!' if value.text.nil? || value.text.size.zero?
155
+ if value.text.nil? || value.text.size.zero?
156
+ raise '[Error] tags label empty!'
157
+ end
158
+
149
159
  @data[:tags] = value.text.split(',')
150
160
  @data[:tags].collect!(&:strip)
151
161
  end
152
162
 
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
-
163
+ # rubocop:disable Metrics/AbcSize
164
+ # rubocop:disable Metrics/MethodLength
170
165
  def process_def(value)
171
166
  case value.attributes['type']
172
167
  when 'image'
@@ -180,4 +175,6 @@ class Concept
180
175
  @data[:texts] << value.text.strip
181
176
  end
182
177
  end
178
+ # rubocop:enable Metrics/AbcSize
179
+ # rubocop:enable Metrics/MethodLength
183
180
  end
@@ -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