asker-tool 2.1.5 → 2.2.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -17
  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 +13 -3
  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 +19 -11
  23. data/lib/asker/cli.rb +31 -44
  24. data/lib/asker/data/code.rb +62 -0
  25. data/lib/asker/data/column.rb +31 -21
  26. data/lib/asker/data/concept.rb +109 -65
  27. data/lib/asker/data/data_field.rb +14 -0
  28. data/lib/asker/data/project_data.rb +63 -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 +51 -35
  33. data/lib/asker/displayer/code_displayer.rb +7 -0
  34. data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
  35. data/lib/asker/displayer/concept_ai_displayer.rb +74 -53
  36. data/lib/asker/displayer/concept_displayer.rb +16 -9
  37. data/lib/asker/displayer/stats_displayer.rb +12 -3
  38. data/lib/asker/exporter/concept_ai_gift_exporter.rb +19 -11
  39. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
  40. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +13 -6
  41. data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
  42. data/lib/asker/exporter/data_gift_exporter.rb +29 -0
  43. data/lib/asker/exporter/output_file_exporter.rb +9 -6
  44. data/lib/asker/files/{config.ini → asker.ini} +48 -1
  45. data/lib/asker/files/example-concept.haml +0 -1
  46. data/lib/asker/files/language/du/connectors.yaml +81 -0
  47. data/lib/asker/{lang/locales/fr → files/language/du}/mistakes.yaml +1 -1
  48. data/lib/asker/files/language/du/templates.yaml +29 -0
  49. data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
  50. data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
  51. data/lib/asker/files/language/en/templates.yaml +29 -0
  52. data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
  53. data/lib/asker/files/language/es/mistakes.yaml +84 -0
  54. data/lib/asker/files/language/es/templates.yaml +29 -0
  55. data/lib/asker/files/language/fr/connectors.yaml +76 -0
  56. data/lib/asker/{lang/locales/es → files/language/fr}/mistakes.yaml +0 -0
  57. data/lib/asker/files/language/fr/templates.yaml +29 -0
  58. data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
  59. data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
  60. data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
  61. data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
  62. data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
  63. data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
  64. data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
  65. data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
  66. data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
  67. data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
  68. data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
  69. data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
  70. data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
  71. data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
  72. data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
  73. data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
  74. data/lib/asker/formatter/concept_string_formatter.rb +7 -4
  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/{checker.rb → input_checker.rb} +126 -49
  82. data/lib/asker/lang/lang.rb +17 -10
  83. data/lib/asker/lang/lang_factory.rb +32 -5
  84. data/lib/asker/lang/text_actions.rb +87 -69
  85. data/lib/asker/loader/code_loader.rb +4 -4
  86. data/lib/asker/loader/content_loader.rb +21 -19
  87. data/lib/asker/loader/directory_loader.rb +1 -8
  88. data/lib/asker/loader/embedded_file.rb +42 -0
  89. data/lib/asker/loader/file_loader.rb +3 -14
  90. data/lib/asker/loader/haml_loader.rb +15 -0
  91. data/lib/asker/loader/image_url_loader.rb +8 -12
  92. data/lib/asker/loader/input_loader.rb +13 -15
  93. data/lib/asker/loader/project_loader.rb +25 -15
  94. data/lib/asker/logger.rb +36 -9
  95. data/lib/asker/skeleton.rb +23 -13
  96. data/lib/asker.rb +76 -42
  97. metadata +53 -54
  98. data/lib/asker/code/ai/base_code_ai.rb +0 -48
  99. data/lib/asker/code/code.rb +0 -53
  100. data/lib/asker/lang/locales/du/templates.yaml +0 -50
  101. data/lib/asker/lang/locales/en/templates.yaml +0 -29
  102. data/lib/asker/lang/locales/es/templates.yaml +0 -29
  103. data/lib/asker/lang/locales/fr/connectors.yaml +0 -92
  104. data/lib/asker/lang/locales/fr/templates.yaml +0 -29
  105. data/lib/asker/project.rb +0 -172
@@ -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
@@ -1,50 +1,23 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require_relative '../loader/image_url_loader'
3
- require_relative '../project'
4
- require_relative '../logger'
5
4
 
6
5
  class World
7
6
  attr_reader :concepts, :filenames, :contexts, :image_urls
8
7
 
9
- def initialize(concepts, show_progress=true)
8
+ def initialize(concepts, internet = true)
10
9
  find_neighbors_for_every_concept(concepts)
11
-
12
- @concepts = {}
13
- @filenames = []
14
- @contexts = []
15
- @image_urls = {}
16
-
17
- concepts.each do |c|
18
- if c.process
19
- @concepts[c.name] = c
20
- @filenames << c.filename
21
- @contexts << c.context
22
- end
23
- end
24
- @filenames.uniq!
25
- @contexts.uniq!
26
-
27
- Logger.verbose "\n[INFO] Loading data from Internet" if show_progress
28
- threads = []
29
- concepts.each do |c|
30
- print('.') if show_progress
31
- # puts "[DEBUG] #{c.name}\n"
32
- # filter = [ c.name.clone ] + c.context.clone
33
- filter = c.name.clone
34
- threads << Thread.new { @image_urls[c.name] = ImageUrlLoader::load(filter) }
35
- end
36
- @contexts.each do |filter|
37
- print('.') if show_progress
38
- threads << Thread.new { @image_urls[ filter.join('.').to_s ] = ImageUrlLoader::load(filter) }
39
- end
40
- threads.each { |t| t.join } # wait for all threads to finish
41
- print("\n") if show_progress
10
+ @concepts, @filenames, @contexts = get_lists_from(concepts)
11
+ @image_urls = find_url_images_from_internet(internet)
42
12
  end
43
13
 
14
+ ##
15
+ # For every concept... find its neighbors
16
+ # @param concepts (Array)
44
17
  def find_neighbors_for_every_concept(concepts)
45
18
  concepts.each do |i|
46
19
  concepts.each do |j|
47
- if (i.id!=j.id) then
20
+ if i.id != j.id
48
21
  i.try_adding_neighbor(j)
49
22
  i.try_adding_references(j)
50
23
  end
@@ -52,4 +25,47 @@ class World
52
25
  end
53
26
  end
54
27
 
28
+ private
29
+
30
+ # rubocop:disable Metrics/MethodLength
31
+ def get_lists_from(input)
32
+ concepts = {}
33
+ filenames = []
34
+ contexts = []
35
+ input.each do |c|
36
+ next unless c.process
37
+
38
+ concepts[c.name] = c
39
+ filenames << c.filename
40
+ contexts << c.context
41
+ end
42
+ filenames.uniq!
43
+ contexts.uniq!
44
+ [concepts, filenames, contexts]
45
+ end
46
+ # rubocop:enable Metrics/MethodLength
47
+
48
+ # rubocop:disable Metrics/MethodLength
49
+ # rubocop:disable Metrics/AbcSize
50
+ # rubocop:disable Metrics/CyclomaticComplexity
51
+ # rubocop:disable Metrics/PerceivedComplexity
52
+ def find_url_images_from_internet(internet)
53
+ return {} unless internet
54
+
55
+ threads = []
56
+ searchs = []
57
+ urls = {}
58
+
59
+ @concepts&.each_key { |key| searchs << key }
60
+ @contexts.each { |filter| searchs << filter.join(' ').to_s }
61
+ searchs.each do |search|
62
+ threads << Thread.new { urls[search] = ImageUrlLoader.load(search) }
63
+ end
64
+ threads.each(&:join) # wait for all threads to finish
65
+ urls
66
+ end
67
+ # rubocop:enable Metrics/MethodLength
68
+ # rubocop:enable Metrics/AbcSize
69
+ # rubocop:enable Metrics/CyclomaticComplexity
70
+ # rubocop:enable Metrics/PerceivedComplexity
55
71
  end
@@ -5,6 +5,11 @@ require_relative '../logger'
5
5
 
6
6
  # Export Code into Screen
7
7
  module CodeDisplayer
8
+ ##
9
+ # Show all "code" data on screen
10
+ # @param codes (Array) List of "code" data
11
+ # rubocop:disable Metrics/AbcSize
12
+ # rubocop:disable Metrics/MethodLength
8
13
  def self.show(codes)
9
14
  return if codes.nil? || codes.size.zero?
10
15
 
@@ -42,4 +47,6 @@ module CodeDisplayer
42
47
  Logger.verboseln "\n[INFO] Showing CODE statistics"
43
48
  Logger.verboseln my_screen_table.to_s
44
49
  end
50
+ # rubocop:enable Metrics/AbcSize
51
+ # rubocop:enable Metrics/MethodLength
45
52
  end
@@ -0,0 +1,10 @@
1
+
2
+ [INFO] Showing CONCEPT statistics
3
+ * Exclude questions: <%= exclude_questions %>
4
+ * Annotations:
5
+ ├── (d) Definitions <= Concept.def
6
+ ├── (b) Table Matching <= Concept.table.rows.columns
7
+ ├── (f) Tables 1 Field <= Concept.table.fields.size==1
8
+ ├── (i) Images URL <= Concept.def{:type => 'file'}
9
+ ├── (s) Sequences <= Concept.table{:sequence => '...'}
10
+ └── (t) Table Rows&Cols <= Concept.table.rows.columns
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erb'
3
4
  require 'terminal-table'
5
+ require_relative '../application'
4
6
  require_relative '../logger'
5
7
 
6
8
  # Display ConceptAI stat on screen
@@ -8,11 +10,23 @@ class ConceptAIDisplayer
8
10
  ##
9
11
  # Display ConceptAI stat on screen
10
12
  # @param concepts_ai (Array)
13
+ # rubocop:disable Metrics/MethodLength
14
+ # rubocop:disable Metrics/AbcSize
15
+ # rubocop:disable Metrics/CyclomaticComplexity
16
+ # rubocop:disable Metrics/PerceivedComplexity
11
17
  def self.show(concepts_ai)
18
+ stages = Application.instance.config['questions']['stages']
12
19
  # Create table HEAD
13
20
  screen_table = Terminal::Table.new do |st|
14
- st << ['Concept','Questions','Entries','xFactor',
15
- 'd','b','f','i','s','t']
21
+ title = %w[Concept Questions Entries xFactor]
22
+ %w[d b f i s t].each do |i|
23
+ if stages.include? i.to_sym
24
+ title << i
25
+ next
26
+ end
27
+ title << Rainbow(i).yellow.bright
28
+ end
29
+ st << title
16
30
  st << :separator
17
31
  end
18
32
  # Create table BODY
@@ -22,32 +36,38 @@ class ConceptAIDisplayer
22
36
  total[:si] = total[:ss] = total[:st] = 0
23
37
 
24
38
  concepts_ai.each do |concept_ai|
25
- if concept_ai.process?
26
- e = concept_ai.texts.size
27
- concept_ai.tables.each { |t| e += t.fields.size * t.rows.size }
39
+ next unless concept_ai.concept.process?
28
40
 
29
- sd = concept_ai.questions[:d].size
30
- sb = concept_ai.questions[:b].size
31
- sf = concept_ai.questions[:f].size
32
- si = concept_ai.questions[:i].size
33
- ss = concept_ai.questions[:s].size
34
- st = concept_ai.questions[:t].size
35
- t = sd + sb + sf + si + ss + st
41
+ e = concept_ai.concept.texts.size
42
+ e += concept_ai.concept.images.size
43
+ concept_ai.concept.tables.each { |t| e += t.fields.size * t.rows.size }
36
44
 
37
- if e == 0
38
- factor = 'Unkown'
39
- else
40
- factor = (t.to_f/e.to_f).round(2).to_s
41
- end
42
- screen_table.add_row [Rainbow(concept_ai.name(:screen)).green.bright,
43
- t, e, factor, sd, sb, sf, si, ss, st]
45
+ sd = sb = sf = 0
46
+ si = ss = st = 0
47
+ sd = concept_ai.questions[:d].size if stages.include? :d
48
+ sb = concept_ai.questions[:b].size if stages.include? :b
49
+ sf = concept_ai.questions[:f].size if stages.include? :f
50
+ si = concept_ai.questions[:i].size if stages.include? :i
51
+ ss = concept_ai.questions[:s].size if stages.include? :s
52
+ st = concept_ai.questions[:t].size if stages.include? :t
53
+ t = sd + sb + sf + si + ss + st
44
54
 
45
- total[:q] += t ; total[:e] += e; total[:c] += 1
46
- total[:sd] += sd; total[:sb] += sb; total[:sf] += sf
47
- total[:si] += si; total[:ss] += ss; total[:st] += st
48
- end
55
+ factor = 'Unkown'
56
+ factor = (t.to_f / e).round(2).to_s unless e.zero?
57
+ screen_table.add_row [Rainbow(concept_ai.concept.name(:screen)).green.bright,
58
+ t, e, factor, sd, sb, sf, si, ss, st]
59
+
60
+ total[:q] += t
61
+ total[:e] += e
62
+ total[:c] += 1
63
+ total[:sd] += sd
64
+ total[:sb] += sb
65
+ total[:sf] += sf
66
+ total[:si] += si
67
+ total[:ss] += ss
68
+ total[:st] += st
49
69
  end
50
- return if total[:c] == 0 # No concepts to be process?
70
+ return if total[:c].zero? # No concepts to be process?
51
71
 
52
72
  # Add row with excluded questions
53
73
  export_excluded_questions(screen_table, concepts_ai)
@@ -57,13 +77,19 @@ class ConceptAIDisplayer
57
77
  screen_table.add_row [Rainbow("TOTAL = #{total[:c]}").bright,
58
78
  Rainbow(total[:q].to_s).bright,
59
79
  Rainbow(total[:e].to_s).bright,
60
- Rainbow((total[:q].to_f/total[:e].to_f).round(2)).bright,
80
+ Rainbow((total[:q].to_f / total[:e]).round(2)).bright,
61
81
  total[:sd], total[:sb], total[:sf],
62
82
  total[:si], total[:ss], total[:st]]
63
83
  export_notes
64
- Logger.verbose "#{screen_table}\n"
84
+ Logger.verboseln "#{screen_table}\n"
65
85
  end
86
+ # rubocop:enable Metrics/MethodLength
87
+ # rubocop:enable Metrics/AbcSize
88
+ # rubocop:enable Metrics/CyclomaticComplexity
89
+ # rubocop:enable Metrics/PerceivedComplexity
66
90
 
91
+ # rubocop:disable Metrics/MethodLength
92
+ # rubocop:disable Metrics/AbcSize
67
93
  private_class_method def self.export_excluded_questions(screen_table, concepts_ai)
68
94
  # Create table BODY
69
95
  total = {}
@@ -72,19 +98,24 @@ class ConceptAIDisplayer
72
98
  total[:si] = total[:ss] = total[:st] = 0
73
99
 
74
100
  concepts_ai.each do |concept_ai|
75
- if concept_ai.process?
76
- sd = concept_ai.excluded_questions[:d].size
77
- sb = concept_ai.excluded_questions[:b].size
78
- sf = concept_ai.excluded_questions[:f].size
79
- si = concept_ai.excluded_questions[:i].size
80
- ss = concept_ai.excluded_questions[:s].size
81
- st = concept_ai.excluded_questions[:t].size
82
- t = sd + sb + sf + si + ss + st
101
+ next unless concept_ai.concept.process?
83
102
 
84
- total[:q] += t ; total[:c] += 1
85
- total[:sd] += sd; total[:sb] += sb; total[:sf] += sf
86
- total[:si] += si; total[:ss] += ss; total[:st] += st
87
- end
103
+ sd = concept_ai.excluded_questions[:d].size
104
+ sb = concept_ai.excluded_questions[:b].size
105
+ sf = concept_ai.excluded_questions[:f].size
106
+ si = concept_ai.excluded_questions[:i].size
107
+ ss = concept_ai.excluded_questions[:s].size
108
+ st = concept_ai.excluded_questions[:t].size
109
+ t = sd + sb + sf + si + ss + st
110
+
111
+ total[:q] += t
112
+ total[:c] += 1
113
+ total[:sd] += sd
114
+ total[:sb] += sb
115
+ total[:sf] += sf
116
+ total[:si] += si
117
+ total[:ss] += ss
118
+ total[:st] += st
88
119
  end
89
120
  screen_table.add_row [Rainbow('Excluded questions').yellow.bright,
90
121
  total[:q], '-', '-',
@@ -92,22 +123,12 @@ class ConceptAIDisplayer
92
123
  total[:sf], total[:si],
93
124
  total[:ss], total[:st]]
94
125
  end
126
+ # rubocop:enable Metrics/MethodLength
127
+ # rubocop:enable Metrics/AbcSize
95
128
 
96
129
  private_class_method def self.export_notes
97
- Logger.verbose "\n[INFO] Showing CONCEPT statistics\n"
98
- Logger.verbose ' * Exclude questions: ' +
99
- Application.instance.config['questions']['exclude'].to_s
100
- Logger.verbose ' * Annotations:'
101
- Logger.verbose ' ├── (d) Definitions <= Concept.def'
102
- Logger.verbose ' ├── (b) Table Matching <= ' \
103
- 'Concept.table.rows.columns'
104
- Logger.verbose ' ├── (f) Tables 1 Field <= Concept.table.fields.size==1'
105
- Logger.verbose ' ├── (i) Images URL <= ' \
106
- "Concept.def{:type => 'image_url'}"
107
- Logger.verbose ' ├── (s) Sequences <= ' \
108
- "Concept.table{:sequence => '...'}"
109
- Logger.verbose ' └── (t) Table Rows&Cols <= ' \
110
- 'Concept.table.rows.columns'
111
- Logger.verbose "\n"
130
+ exclude_questions = Application.instance.config['questions']['exclude'].to_s
131
+ renderer = ERB.new(File.read(File.join(File.dirname(__FILE__), 'concept_ai_displayer.erb')))
132
+ Logger.verboseln renderer.result(binding)
112
133
  end
113
134
  end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
 
3
+ require_relative '../application'
2
4
  require_relative '../formatter/concept_string_formatter'
3
5
  require_relative '../logger'
4
6
 
@@ -6,22 +8,27 @@ require_relative '../logger'
6
8
  module ConceptDisplayer
7
9
  ##
8
10
  # Show concepts on screen
9
- # @param concepts (Array)
10
- # @param show_mode (Symbol)
11
- def self.show(concepts, show_mode = :default)
12
- return if show_mode == :none
11
+ # @param concepts (Array) List of concept data
12
+ # rubocop:disable Metrics/AbcSize
13
+ # rubocop:disable Metrics/MethodLength
14
+ def self.show(concepts)
15
+ show_mode = Application.instance.config['global']['show_mode']
16
+ return unless show_mode
17
+
13
18
  msg = "\n[INFO] Showing concept data (#{Rainbow(show_mode).bright})"
14
- Logger.verbose msg
19
+ Logger.verboseln msg
15
20
  case show_mode
16
- when :resume
21
+ when 'resume'
17
22
  s = "* Concepts (#{concepts.count}): "
18
23
  concepts.each { |c| s += c.name + ', ' }
19
- Logger.verbose s
20
- when :default
24
+ Logger.verboseln s
25
+ when 'default'
21
26
  # Only show Concepts with process attr true
22
27
  concepts.each do |c|
23
- Logger.verbose ConceptStringFormatter.to_s(c) if c.process?
28
+ Logger.verboseln ConceptStringFormatter.to_s(c) if c.process?
24
29
  end
25
30
  end
26
31
  end
32
+ # rubocop:enable Metrics/AbcSize
33
+ # rubocop:enable Metrics/MethodLength
27
34
  end
@@ -1,13 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../application'
1
4
  require_relative 'concept_ai_displayer'
2
5
  require_relative 'code_displayer'
3
6
 
4
7
  # Display Stats on screen.
8
+ # * Display all "Concept AI"
9
+ # * Display all "Code"
5
10
  module StatsDisplayer
6
- def self.show(data, show_mode)
7
- return if show_mode == :none
11
+ # Display Stats on screen.
12
+ # * Display all "Concept AI"
13
+ # * Display all "Code"
14
+ # @param data (Hash) With concept_ai list and code list
15
+ def self.show(data)
16
+ return unless Application.instance.config['global']['show_mode']
8
17
 
9
18
  # show_final_results
10
19
  ConceptAIDisplayer.show(data[:concepts_ai])
11
- CodeDisplayer.show(data[:codes])
20
+ CodeDisplayer.show(data[:codes_ai])
12
21
  end
13
22
  end
@@ -1,29 +1,37 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require_relative '../project'
4
3
  require_relative '../formatter/question_gift_formatter'
5
4
 
6
5
  # Export ConceptIA data to gift to outputfile
7
6
  module ConceptAIGiftExporter
8
7
  ##
9
- # Export list of ConceptAI into outpufile
10
- def self.export_all(concepts_ai, project)
11
- concepts_ai.each { |concept_ai| export(concept_ai, project) }
8
+ # Export an array of ConceptAI objects from Project into GIFT outpufile
9
+ # @param concepts_ai (Array)
10
+ # @param file (File)
11
+ def self.export_all(concepts_ai, file)
12
+ concepts_ai.each { |concept_ai| export(concept_ai, file) }
12
13
  end
13
14
 
14
- def self.export(concept_ai, project)
15
- return unless concept_ai.process?
15
+ ##
16
+ # Export 1 concept_ai from project
17
+ # @param concept_ai (ConceptAI)
18
+ # @param file (File)
19
+ private_class_method def self.export(concept_ai, file)
20
+ return unless concept_ai.concept.process?
16
21
 
17
- file = project.get(:outputfile)
18
- file.write head(concept_ai.name)
19
- project.stages.each_key do |stage|
22
+ file.write head(concept_ai.concept.name)
23
+ Application.instance.config['questions']['stages'].each do |stage|
20
24
  concept_ai.questions[stage].each do |question|
21
25
  file.write(QuestionGiftFormatter.to_s(question))
22
26
  end
23
27
  end
24
28
  end
25
29
 
26
- def self.head(name)
30
+ ##
31
+ # Convert Concept name into gift format head
32
+ # @param name (String)
33
+ # @return String
34
+ private_class_method def self.head(name)
27
35
  s = "\n"
28
36
  s += '// ' + '=' * 50 + "\n"
29
37
  s += "// Concept name: #{name}\n"