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.
- checksums.yaml +4 -4
- data/README.md +13 -17
- data/bin/asker +2 -1
- data/lib/asker/ai/ai.rb +10 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/code/base_code_ai.rb +104 -0
- data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
- data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
- data/lib/asker/ai/code/problem_code_ai.rb +176 -0
- data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
- data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
- data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
- data/lib/asker/ai/concept_ai.rb +13 -3
- data/lib/asker/ai/question.rb +28 -6
- data/lib/asker/ai/stages/base_stage.rb +45 -6
- data/lib/asker/ai/stages/stage_b.rb +100 -50
- data/lib/asker/ai/stages/stage_d.rb +75 -90
- data/lib/asker/ai/stages/stage_f.rb +64 -36
- data/lib/asker/ai/stages/stage_i.rb +79 -92
- data/lib/asker/ai/stages/stage_s.rb +41 -36
- data/lib/asker/ai/stages/stage_t.rb +149 -108
- data/lib/asker/application.rb +19 -11
- data/lib/asker/cli.rb +31 -44
- data/lib/asker/data/code.rb +62 -0
- data/lib/asker/data/column.rb +31 -21
- data/lib/asker/data/concept.rb +109 -65
- data/lib/asker/data/data_field.rb +14 -0
- data/lib/asker/data/project_data.rb +63 -0
- data/lib/asker/data/row.rb +75 -52
- data/lib/asker/data/table.rb +91 -42
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +51 -35
- data/lib/asker/displayer/code_displayer.rb +7 -0
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +74 -53
- data/lib/asker/displayer/concept_displayer.rb +16 -9
- data/lib/asker/displayer/stats_displayer.rb +12 -3
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +19 -11
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +13 -6
- data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +9 -6
- data/lib/asker/files/{config.ini → asker.ini} +48 -1
- data/lib/asker/files/example-concept.haml +0 -1
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/{lang/locales/fr → files/language/du}/mistakes.yaml +1 -1
- data/lib/asker/files/language/du/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
- data/lib/asker/files/language/en/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
- data/lib/asker/files/language/es/mistakes.yaml +84 -0
- data/lib/asker/files/language/es/templates.yaml +29 -0
- data/lib/asker/files/language/fr/connectors.yaml +76 -0
- data/lib/asker/{lang/locales/es → files/language/fr}/mistakes.yaml +0 -0
- data/lib/asker/files/language/fr/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
- data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
- data/lib/asker/formatter/concept_string_formatter.rb +7 -4
- data/lib/asker/formatter/moodle/matching.erb +38 -0
- data/lib/asker/formatter/moodle/multichoice.erb +49 -0
- data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
- data/lib/asker/formatter/moodle/truefalse.erb +47 -0
- data/lib/asker/formatter/question_gift_formatter.rb +30 -20
- data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
- data/lib/asker/{checker.rb → input_checker.rb} +126 -49
- data/lib/asker/lang/lang.rb +17 -10
- data/lib/asker/lang/lang_factory.rb +32 -5
- data/lib/asker/lang/text_actions.rb +87 -69
- data/lib/asker/loader/code_loader.rb +4 -4
- data/lib/asker/loader/content_loader.rb +21 -19
- data/lib/asker/loader/directory_loader.rb +1 -8
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +3 -14
- data/lib/asker/loader/haml_loader.rb +15 -0
- data/lib/asker/loader/image_url_loader.rb +8 -12
- data/lib/asker/loader/input_loader.rb +13 -15
- data/lib/asker/loader/project_loader.rb +25 -15
- data/lib/asker/logger.rb +36 -9
- data/lib/asker/skeleton.rb +23 -13
- data/lib/asker.rb +76 -42
- metadata +53 -54
- data/lib/asker/code/ai/base_code_ai.rb +0 -48
- data/lib/asker/code/code.rb +0 -53
- data/lib/asker/lang/locales/du/templates.yaml +0 -50
- data/lib/asker/lang/locales/en/templates.yaml +0 -29
- data/lib/asker/lang/locales/es/templates.yaml +0 -29
- data/lib/asker/lang/locales/fr/connectors.yaml +0 -92
- data/lib/asker/lang/locales/fr/templates.yaml +0 -29
- data/lib/asker/project.rb +0 -172
data/lib/asker/data/table.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
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, :
|
|
10
|
-
attr_reader :
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
data/lib/asker/data/template.rb
CHANGED
|
@@ -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
|
data/lib/asker/data/world.rb
CHANGED
|
@@ -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,
|
|
8
|
+
def initialize(concepts, internet = true)
|
|
10
9
|
find_neighbors_for_every_concept(concepts)
|
|
11
|
-
|
|
12
|
-
@
|
|
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
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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]
|
|
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]
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
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.
|
|
19
|
+
Logger.verboseln msg
|
|
15
20
|
case show_mode
|
|
16
|
-
when
|
|
21
|
+
when 'resume'
|
|
17
22
|
s = "* Concepts (#{concepts.count}): "
|
|
18
23
|
concepts.each { |c| s += c.name + ', ' }
|
|
19
|
-
Logger.
|
|
20
|
-
when
|
|
24
|
+
Logger.verboseln s
|
|
25
|
+
when 'default'
|
|
21
26
|
# Only show Concepts with process attr true
|
|
22
27
|
concepts.each do |c|
|
|
23
|
-
Logger.
|
|
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
|
-
|
|
7
|
-
|
|
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[:
|
|
20
|
+
CodeDisplayer.show(data[:codes_ai])
|
|
12
21
|
end
|
|
13
22
|
end
|
|
@@ -1,29 +1,37 @@
|
|
|
1
|
-
#
|
|
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
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
|
18
|
-
|
|
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
|
-
|
|
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"
|