asker-tool 2.6.0 → 2.7.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 +5 -5
- data/lib/asker/ai/ai.rb +6 -6
- data/lib/asker/ai/ai_calculate.rb +3 -3
- data/lib/asker/ai/code/base_code_ai.rb +5 -30
- data/lib/asker/ai/code/code_ai_factory.rb +6 -12
- data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
- data/lib/asker/ai/code/python_code_ai.rb +35 -36
- data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
- data/lib/asker/ai/code/sql_code_ai.rb +20 -21
- data/lib/asker/ai/concept_ai.rb +12 -22
- data/lib/asker/ai/problem/problem_ai.rb +226 -0
- data/lib/asker/ai/question.rb +34 -45
- data/lib/asker/ai/stages/base_stage.rb +7 -7
- data/lib/asker/ai/stages/stage_b.rb +62 -28
- data/lib/asker/ai/stages/stage_d.rb +10 -10
- data/lib/asker/ai/stages/stage_f.rb +17 -17
- data/lib/asker/ai/stages/stage_i.rb +8 -18
- data/lib/asker/ai/stages/stage_s.rb +28 -26
- data/lib/asker/ai/stages/stage_t.rb +40 -51
- data/lib/asker/application.rb +15 -14
- data/lib/asker/check_input/check_haml_data.rb +52 -51
- data/lib/asker/check_input/check_table.rb +17 -20
- data/lib/asker/check_input.rb +10 -23
- data/lib/asker/cli.rb +43 -24
- data/lib/asker/data/code.rb +10 -9
- data/lib/asker/data/column.rb +21 -17
- data/lib/asker/data/concept.rb +24 -37
- data/lib/asker/data/data_field.rb +2 -2
- data/lib/asker/data/problem.rb +112 -0
- data/lib/asker/data/project_data.rb +11 -15
- data/lib/asker/data/row.rb +25 -23
- data/lib/asker/data/table.rb +25 -46
- data/lib/asker/data/template.rb +7 -7
- data/lib/asker/data/world.rb +3 -3
- data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
- data/lib/asker/displayer/code_displayer.rb +10 -10
- data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
- data/lib/asker/displayer/concept_ai_displayer.rb +17 -17
- data/lib/asker/displayer/concept_displayer.rb +4 -2
- data/lib/asker/displayer/problem_displayer.rb +45 -0
- data/lib/asker/displayer/stats_displayer.rb +7 -12
- data/lib/asker/exporter/code_gift_exporter.rb +2 -2
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
- data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
- data/lib/asker/exporter/data_gift_exporter.rb +14 -15
- data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
- data/lib/asker/exporter/output_file_exporter.rb +9 -8
- data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
- data/lib/asker/files/language/ca/templates.yaml +6 -0
- data/lib/asker/files/language/du/templates.yaml +6 -0
- data/lib/asker/files/language/en/templates.yaml +7 -1
- data/lib/asker/files/language/es/templates.yaml +6 -0
- data/lib/asker/files/language/fr/templates.yaml +6 -0
- data/lib/asker/formatter/code_string_formatter.rb +5 -5
- data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
- data/lib/asker/formatter/concept_string_formatter.rb +6 -6
- data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
- data/lib/asker/formatter/moodle/gapfill.erb +57 -0
- data/lib/asker/formatter/moodle/ordering.erb +41 -0
- data/lib/asker/formatter/question_gift_formatter.rb +41 -14
- data/lib/asker/formatter/question_hash_formatter.rb +5 -6
- data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
- data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
- data/lib/asker/lang/lang.rb +16 -16
- data/lib/asker/lang/lang_factory.rb +13 -16
- data/lib/asker/lang/text_actions.rb +20 -18
- data/lib/asker/loader/code_loader.rb +10 -22
- data/lib/asker/loader/content_loader.rb +42 -49
- data/lib/asker/loader/directory_loader.rb +13 -16
- data/lib/asker/loader/embedded_file.rb +14 -14
- data/lib/asker/loader/file_loader.rb +5 -4
- data/lib/asker/loader/haml_loader.rb +4 -3
- data/lib/asker/loader/image_url_loader.rb +6 -5
- data/lib/asker/loader/input_loader.rb +24 -10
- data/lib/asker/loader/problem_loader.rb +88 -0
- data/lib/asker/loader/project_loader.rb +5 -12
- data/lib/asker/logger.rb +19 -10
- data/lib/asker/skeleton.rb +19 -35
- data/lib/asker/start.rb +44 -0
- data/lib/asker/version.rb +1 -1
- data/lib/asker.rb +7 -52
- metadata +12 -6
- data/lib/asker/ai/code/problem_code_ai.rb +0 -176
- data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
data/lib/asker/data/table.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "row"
|
4
|
+
require_relative "template"
|
5
|
+
require_relative "../logger"
|
5
6
|
|
6
|
-
# Contains data table information
|
7
7
|
class Table
|
8
8
|
attr_reader :name, :id
|
9
9
|
attr_reader :fields, :sequence
|
@@ -14,30 +14,25 @@ class Table
|
|
14
14
|
attr_reader :simple
|
15
15
|
|
16
16
|
##
|
17
|
-
# initialize Table object
|
18
17
|
# @param concept (Concept)
|
19
18
|
# @param xml_data (XML)
|
20
19
|
def initialize(concept, xml_data)
|
21
20
|
@concept = concept
|
22
21
|
read_attributes_from_xml(xml_data)
|
23
22
|
|
24
|
-
@simple = {
|
25
|
-
@types
|
26
|
-
@langs
|
23
|
+
@simple = {lang: true, type: true}
|
24
|
+
@types = ["text"] * @fields.size
|
25
|
+
@langs = [@concept.lang] * @fields.size
|
27
26
|
|
28
27
|
@datarows = [] # DEV experiment replace row data with row objects
|
29
28
|
read_data_from_xml(xml_data)
|
30
29
|
@rows = @datarows.map(&:raws)
|
31
30
|
end
|
32
31
|
|
33
|
-
##
|
34
|
-
# Return table name
|
35
32
|
def to_s
|
36
33
|
@name.to_s
|
37
34
|
end
|
38
35
|
|
39
|
-
##
|
40
|
-
# Return true if table has a sequence defined
|
41
36
|
def sequence?
|
42
37
|
@sequence.size.positive?
|
43
38
|
end
|
@@ -48,7 +43,7 @@ class Table
|
|
48
43
|
# * types(index) => Return type for fields[index]
|
49
44
|
# @param index (Integer)
|
50
45
|
def types(index = :all)
|
51
|
-
@types = ([
|
46
|
+
@types = (["text"] * @fields.size) if @types.nil?
|
52
47
|
return @types if index == :all
|
53
48
|
|
54
49
|
@types[index]
|
@@ -68,75 +63,59 @@ class Table
|
|
68
63
|
##
|
69
64
|
# Fill:fields, name and id from XML input
|
70
65
|
# @param xml_data (XML)
|
71
|
-
# rubocop:disable Metrics/AbcSize
|
72
66
|
def read_attributes_from_xml(xml_data)
|
73
|
-
|
74
|
-
t = xml_data.attributes['fields'].to_s.strip.split(',')
|
67
|
+
t = xml_data.attributes["fields"].to_s.strip.split(",")
|
75
68
|
t.each(&:strip!)
|
76
69
|
@fields = t || []
|
77
70
|
|
78
|
-
@name =
|
71
|
+
@name = ""
|
79
72
|
@fields.each { |i| @name = "#{@name}$#{i.to_s.strip.downcase}" }
|
80
73
|
@id = "#{@concept.name}.#{@name}"
|
81
74
|
|
82
75
|
@sequence = []
|
83
|
-
return unless xml_data.attributes[
|
76
|
+
return unless xml_data.attributes["sequence"]
|
84
77
|
|
85
|
-
@sequence = xml_data.attributes[
|
78
|
+
@sequence = xml_data.attributes["sequence"].to_s.split(",")
|
86
79
|
end
|
87
|
-
# rubocop:enable Metrics/AbcSize
|
88
80
|
|
89
|
-
##
|
90
|
-
# Build table data from xml input
|
91
|
-
# @param xml_data (XML)
|
92
|
-
# rubocop:disable Metrics/MethodLength
|
93
|
-
# rubocop:disable Metrics/AbcSize
|
94
81
|
def read_data_from_xml(xml_data)
|
95
82
|
xml_data.elements.each do |i|
|
96
83
|
case i.name
|
97
|
-
when
|
84
|
+
when "lang"
|
98
85
|
read_lang_from_xml(i)
|
99
|
-
when
|
86
|
+
when "row"
|
100
87
|
@datarows << Row.new(self, @datarows.size, i)
|
101
|
-
when
|
102
|
-
@sequence = i.text.split(
|
103
|
-
when
|
88
|
+
when "sequence"
|
89
|
+
@sequence = i.text.split(",")
|
90
|
+
when "template"
|
104
91
|
@datarows += Template.new(self, @datarows.size, i).datarows
|
105
|
-
when
|
92
|
+
when "type"
|
106
93
|
read_type_from_xml(i)
|
107
94
|
else
|
108
|
-
|
95
|
+
Logger.warn "Table: Tag unkown (concept/table/#{i.name})"
|
109
96
|
end
|
110
97
|
end
|
111
98
|
end
|
112
|
-
# rubocop:enable Metrics/MethodLength
|
113
|
-
# rubocop:enable Metrics/AbcSize
|
114
99
|
|
115
|
-
# rubocop:disable Metrics/MethodLength
|
116
|
-
# rubocop:disable Metrics/AbcSize
|
117
|
-
# rubocop:disable Style/ConditionalAssignment
|
118
100
|
def read_lang_from_xml(xml_data)
|
119
|
-
j = xml_data.text.split(
|
101
|
+
j = xml_data.text.split(",")
|
120
102
|
codes = @langs.map(&:code)
|
121
|
-
return if j.join(
|
103
|
+
return if j.join(",") == codes.join(",")
|
122
104
|
|
123
105
|
simple_off(:lang)
|
124
106
|
@langs = []
|
125
107
|
j.each do |k|
|
126
|
-
if [
|
127
|
-
@
|
108
|
+
@langs << if ["*", ""].include? k.strip
|
109
|
+
@concept.lang
|
128
110
|
else
|
129
|
-
|
111
|
+
LangFactory.instance.get(k.strip.to_s)
|
130
112
|
end
|
131
113
|
end
|
132
114
|
end
|
133
|
-
# rubocop:enable Metrics/MethodLength
|
134
|
-
# rubocop:enable Metrics/AbcSize
|
135
|
-
# rubocop:enable Style/ConditionalAssignment
|
136
115
|
|
137
116
|
def read_type_from_xml(xml_data)
|
138
|
-
j = xml_data.text.split(
|
139
|
-
return if j.join(
|
117
|
+
j = xml_data.text.split(",")
|
118
|
+
return if j.join(",") == @types.join(",")
|
140
119
|
|
141
120
|
simple_off(:type)
|
142
121
|
@types = []
|
data/lib/asker/data/template.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative
|
3
|
+
require "rexml/document"
|
4
|
+
require_relative "row"
|
5
5
|
|
6
6
|
# This class process "template" tag used by Tables
|
7
7
|
class Template
|
@@ -19,10 +19,10 @@ class Template
|
|
19
19
|
vars = {}
|
20
20
|
v = xml.attributes
|
21
21
|
v.keys.each do |i|
|
22
|
-
if i ==
|
22
|
+
if i == "mode"
|
23
23
|
@mode = v[i].to_sym
|
24
24
|
else
|
25
|
-
vars[i] = v[i].split(
|
25
|
+
vars[i] = v[i].split(",")
|
26
26
|
end
|
27
27
|
end
|
28
28
|
# fill_vars_values(vars,mode)
|
@@ -34,13 +34,13 @@ class Template
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def load_template_from(xml)
|
37
|
-
template =
|
37
|
+
template = ""
|
38
38
|
xml.elements.each { |i| template << i.to_s + "\n" }
|
39
39
|
template
|
40
40
|
end
|
41
41
|
|
42
42
|
def apply_vars_to_template(vars, template)
|
43
|
-
output =
|
43
|
+
output = ""
|
44
44
|
return output if vars.size.zero?
|
45
45
|
|
46
46
|
max = vars.first[1].size
|
@@ -57,7 +57,7 @@ class Template
|
|
57
57
|
data = "<template>\n#{data_string}\n</template>"
|
58
58
|
xml = REXML::Document.new(data)
|
59
59
|
xml.root.elements.each do |i|
|
60
|
-
if i.name ==
|
60
|
+
if i.name == "row"
|
61
61
|
datarows << Row.new(table, index, i)
|
62
62
|
index += 1
|
63
63
|
end
|
data/lib/asker/data/world.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../loader/image_url_loader"
|
4
4
|
|
5
5
|
class World
|
6
6
|
# TODO: change how World class works ?
|
@@ -37,7 +37,7 @@ class World
|
|
37
37
|
|
38
38
|
concepts[c.name] = c
|
39
39
|
filenames << c.filename
|
40
|
-
contexts
|
40
|
+
contexts << c.context
|
41
41
|
end
|
42
42
|
filenames.uniq!
|
43
43
|
contexts.uniq!
|
@@ -52,7 +52,7 @@ class World
|
|
52
52
|
urls = {}
|
53
53
|
|
54
54
|
@concepts&.each_key { |key| searchs << key }
|
55
|
-
@contexts.each { |filter| searchs << filter.join(
|
55
|
+
@contexts.each { |filter| searchs << filter.join(" ").to_s }
|
56
56
|
searchs.each do |search|
|
57
57
|
threads << Thread.new { urls[search] = ImageUrlLoader.load(search) }
|
58
58
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# Transform Questions into Gift format
|
4
2
|
module QuestionMoodleXMLFormatter
|
5
3
|
def self.to_s(question)
|
@@ -18,51 +16,51 @@ module QuestionMoodleXMLFormatter
|
|
18
16
|
def self.choice_to_s(question)
|
19
17
|
s = []
|
20
18
|
|
21
|
-
penalties = [
|
19
|
+
penalties = ["", "%-50%", "%-33.33333%", "%-25%", "%-20%"]
|
22
20
|
penalty = penalties[question.bads.size]
|
23
21
|
|
24
22
|
s << "<!-- question: #{question.name} -->"
|
25
23
|
s << '<question type="multichoice">'
|
26
|
-
s <<
|
24
|
+
s << " <name>"
|
27
25
|
s << " <text>#{question.name}</text>"
|
28
|
-
s <<
|
26
|
+
s << " </name>"
|
29
27
|
s << ' <questiontext format="html">'
|
30
28
|
s << " <text><![CDATA[#{question.text}]]></text>"
|
31
|
-
s <<
|
29
|
+
s << " </questiontext>"
|
32
30
|
s << ' <generalfeedback format="html">'
|
33
31
|
s << " <text>#{question.feedback}</text>"
|
34
|
-
s <<
|
35
|
-
s <<
|
32
|
+
s << " </generalfeedback>"
|
33
|
+
s << " <defaultgrade>1.0000000</defaultgrade>"
|
36
34
|
s << " <penalty>#{penalty}</penalty>"
|
37
|
-
s <<
|
38
|
-
s <<
|
35
|
+
s << " <hidden>0</hidden>"
|
36
|
+
s << " <single>true</single>"
|
39
37
|
s << " <shuffleanswers>#{question.shuffle?}</shuffleanswers>"
|
40
|
-
s <<
|
38
|
+
s << " <answernumbering>abc</answernumbering>"
|
41
39
|
s << ' <incorrectfeedback format="html">'
|
42
40
|
s << " <text>#{question.feedback}</text>"
|
43
|
-
s <<
|
41
|
+
s << " </incorrectfeedback>"
|
44
42
|
s << ' <answer fraction="100" format="html">'
|
45
43
|
s << " <text>#{question.good}</text>"
|
46
|
-
s <<
|
44
|
+
s << " </answer>"
|
47
45
|
s << ' <answer fraction="-25" format="html">'
|
48
46
|
s << " <text>#{question.bad[0]}</text>"
|
49
|
-
s <<
|
50
|
-
s <<
|
47
|
+
s << " </answer>"
|
48
|
+
s << " </question>"
|
51
49
|
s << ' <answer fraction="-25" format="html">'
|
52
50
|
s << " <text>#{question.bad[1]}</text>"
|
53
|
-
s <<
|
54
|
-
s <<
|
51
|
+
s << " </answer>"
|
52
|
+
s << " </question>"
|
55
53
|
s << ' <answer fraction="-25" format="html">'
|
56
54
|
s << " <text>#{question.bad[2]}</text>"
|
57
|
-
s <<
|
58
|
-
s <<
|
55
|
+
s << " </answer>"
|
56
|
+
s << " </question>"
|
59
57
|
s
|
60
58
|
end
|
61
59
|
|
62
|
-
def self.sanitize(input =
|
60
|
+
def self.sanitize(input = "")
|
63
61
|
output = input.dup
|
64
62
|
output.tr!("\n", " ")
|
65
|
-
output.tr!(":", "
|
63
|
+
output.tr!(":", ":")
|
66
64
|
output.tr!("=", "\\=")
|
67
65
|
# output.gsub!('{', "\\{")
|
68
66
|
# output.gsub!('}', "\\}")
|
@@ -19,13 +19,13 @@ module CodeDisplayer
|
|
19
19
|
|
20
20
|
e = code.lines.size
|
21
21
|
q = code.questions.size
|
22
|
-
factor =
|
22
|
+
factor = "Unknown"
|
23
23
|
factor = (q.to_f / e).round(2).to_s unless e.zero?
|
24
24
|
my_screen_table.add_row [Rainbow(File.basename(code.filename)).green,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
code.type,
|
26
|
+
q,
|
27
|
+
e,
|
28
|
+
factor]
|
29
29
|
total_c += 1
|
30
30
|
total_q += q
|
31
31
|
total_e += e
|
@@ -33,13 +33,13 @@ module CodeDisplayer
|
|
33
33
|
|
34
34
|
my_screen_table.add_separator
|
35
35
|
my_screen_table.add_row [Rainbow("TOTAL = #{total_c}").bright,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
" ",
|
37
|
+
Rainbow(total_q.to_s).bright,
|
38
|
+
Rainbow(total_e.to_s).bright,
|
39
|
+
Rainbow((total_q / total_e.to_f).round(2)).bright]
|
40
40
|
return unless total_c.positive?
|
41
41
|
|
42
|
-
Logger.verboseln "\n[INFO] Showing
|
42
|
+
Logger.verboseln "\n[INFO] Showing CODEs statistics"
|
43
43
|
Logger.verboseln my_screen_table.to_s
|
44
44
|
end
|
45
45
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "erb"
|
4
|
+
require "rainbow"
|
4
5
|
require "terminal-table"
|
5
6
|
require_relative "../application"
|
6
7
|
require_relative "../logger"
|
7
8
|
|
8
|
-
# Display ConceptAI stat on screen
|
9
9
|
class ConceptAIDisplayer
|
10
10
|
##
|
11
11
|
# Display ConceptAI stat on screen
|
@@ -48,10 +48,10 @@ class ConceptAIDisplayer
|
|
48
48
|
st = concept_ai.questions[:t].size if stages.include? :t
|
49
49
|
t = sd + sb + sf + si + ss + st
|
50
50
|
|
51
|
-
factor = "
|
51
|
+
factor = "Unknown"
|
52
52
|
factor = (t.to_f / e).round(2).to_s unless e.zero?
|
53
53
|
screen_table.add_row [Rainbow(concept_ai.concept.name(:screen)).green.bright,
|
54
|
-
|
54
|
+
t, e, factor, sd, sb, sf, si, ss, st]
|
55
55
|
|
56
56
|
total[:q] += t
|
57
57
|
total[:e] += e
|
@@ -71,13 +71,13 @@ class ConceptAIDisplayer
|
|
71
71
|
# Create table TAIL
|
72
72
|
screen_table.add_separator
|
73
73
|
screen_table.add_row [Rainbow("#{total[:c]} concept/s").bright,
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
Rainbow(total[:q].to_s).bright,
|
75
|
+
Rainbow(total[:e].to_s).bright,
|
76
|
+
Rainbow((total[:q].to_f / total[:e]).round(2)).bright,
|
77
|
+
total[:sd], total[:sb], total[:sf],
|
78
|
+
total[:si], total[:ss], total[:st]]
|
79
79
|
export_notes
|
80
|
-
Logger.
|
80
|
+
Logger.info "#{screen_table}\n"
|
81
81
|
end
|
82
82
|
|
83
83
|
private_class_method def self.export_excluded_questions(screen_table, concepts_ai)
|
@@ -107,16 +107,16 @@ class ConceptAIDisplayer
|
|
107
107
|
total[:ss] += ss
|
108
108
|
total[:st] += st
|
109
109
|
end
|
110
|
-
screen_table.add_row [Rainbow(
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
screen_table.add_row [Rainbow("Excluded questions").yellow.bright,
|
111
|
+
total[:q], "-", "-",
|
112
|
+
total[:sd], total[:sb],
|
113
|
+
total[:sf], total[:si],
|
114
|
+
total[:ss], total[:st]]
|
115
115
|
end
|
116
116
|
|
117
117
|
private_class_method def self.export_notes
|
118
|
-
exclude_questions = Application.instance.config[
|
119
|
-
renderer = ERB.new(File.read(File.join(File.dirname(__FILE__),
|
120
|
-
Logger.
|
118
|
+
exclude_questions = Application.instance.config["questions"]["exclude"].to_s
|
119
|
+
renderer = ERB.new(File.read(File.join(File.dirname(__FILE__), "concept_ai_displayer.erb")))
|
120
|
+
Logger.info Rainbow(renderer.result(binding)).white
|
121
121
|
end
|
122
122
|
end
|
@@ -7,6 +7,8 @@ module ConceptDisplayer
|
|
7
7
|
# Show concepts on screen
|
8
8
|
# @param concepts (Array) List of concept data
|
9
9
|
def self.show(concepts)
|
10
|
+
return if concepts.nil? || concepts.size.zero?
|
11
|
+
|
10
12
|
show_mode = Application.instance.config["global"]["show_mode"]
|
11
13
|
return unless show_mode
|
12
14
|
|
@@ -14,8 +16,8 @@ module ConceptDisplayer
|
|
14
16
|
Logger.verboseln msg
|
15
17
|
case show_mode
|
16
18
|
when "resume"
|
17
|
-
|
18
|
-
|
19
|
+
names = concepts.map { |c| c.name }
|
20
|
+
s = " * Concepts (#{names.count}): #{names.join(",")}"
|
19
21
|
Logger.verboseln s
|
20
22
|
when "default"
|
21
23
|
# Only show Concepts with process attr true
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "terminal-table"
|
2
|
+
require_relative "../logger"
|
3
|
+
|
4
|
+
module ProblemDisplayer
|
5
|
+
##
|
6
|
+
# Show all "problem" data on screen
|
7
|
+
# @param problems (Array) List of "problems" data
|
8
|
+
def self.show(problems)
|
9
|
+
return if problems.nil? || problems.size.zero?
|
10
|
+
|
11
|
+
total_p = total_q = total_e = 0
|
12
|
+
my_screen_table = Terminal::Table.new do |st|
|
13
|
+
st << %w[Problem Desc Questions Entries xFactor]
|
14
|
+
st << :separator
|
15
|
+
end
|
16
|
+
|
17
|
+
problems.each do |problem|
|
18
|
+
next unless problem.process?
|
19
|
+
|
20
|
+
e = problem.cases.size
|
21
|
+
problem.asks.each do |ask|
|
22
|
+
e += ask[:steps].size
|
23
|
+
e += 1 if !ask[:answer].nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
q = problem.questions.size
|
27
|
+
factor = "Unknown"
|
28
|
+
factor = (q.to_f / e).round(2).to_s unless e.zero?
|
29
|
+
desc = Rainbow(problem.desc[0, 24]).green
|
30
|
+
my_screen_table.add_row [problem.name, desc, q, e, factor]
|
31
|
+
total_p += 1
|
32
|
+
total_q += q
|
33
|
+
total_e += e
|
34
|
+
end
|
35
|
+
return unless total_p.positive?
|
36
|
+
|
37
|
+
my_screen_table.add_separator
|
38
|
+
my_screen_table.add_row [Rainbow("TOTAL = #{total_p}").bright, "",
|
39
|
+
Rainbow(total_q.to_s).bright,
|
40
|
+
Rainbow(total_e.to_s).bright,
|
41
|
+
Rainbow((total_q / total_e.to_f).round(2)).bright]
|
42
|
+
Logger.verboseln Rainbow("\n[INFO] Showing PROBLEMs statistics").white
|
43
|
+
Logger.verboseln my_screen_table.to_s
|
44
|
+
end
|
45
|
+
end
|
@@ -1,22 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative "../application"
|
4
|
+
require_relative "concept_ai_displayer"
|
5
|
+
require_relative "code_displayer"
|
6
|
+
require_relative "problem_displayer"
|
6
7
|
|
7
|
-
# Display Stats on screen.
|
8
|
-
# * Display all "Concept AI"
|
9
|
-
# * Display all "Code"
|
10
8
|
module StatsDisplayer
|
11
|
-
#
|
12
|
-
# * Display all "Concept AI"
|
13
|
-
# * Display all "Code"
|
14
|
-
# @param data (Hash) With concept_ai list and code list
|
9
|
+
# @param data (Hash) With concept_ai, code and problem list
|
15
10
|
def self.show(data)
|
16
|
-
return unless Application.instance.config[
|
11
|
+
return unless Application.instance.config["global"]["show_mode"]
|
17
12
|
|
18
|
-
# show_final_results
|
19
13
|
ConceptAIDisplayer.show(data[:concepts_ai])
|
20
14
|
CodeDisplayer.show(data[:codes_ai])
|
15
|
+
ProblemDisplayer.show(data[:problems])
|
21
16
|
end
|
22
17
|
end
|
@@ -23,9 +23,9 @@ module CodeGiftExporter
|
|
23
23
|
|
24
24
|
private_class_method def self.head(code)
|
25
25
|
s = "\n"
|
26
|
-
s +=
|
26
|
+
s += "// " + "=" * 50 + "\n"
|
27
27
|
s += "// Code #{code.type}: #{code.filename} (#{code.questions.size})\n"
|
28
|
-
s +=
|
28
|
+
s += "// " + "=" * 50 + "\n"
|
29
29
|
s
|
30
30
|
end
|
31
31
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../formatter/question_gift_formatter"
|
4
4
|
|
5
5
|
# Export ConceptIA data to gift to outputfile
|
6
6
|
module ConceptAIGiftExporter
|
@@ -20,7 +20,7 @@ module ConceptAIGiftExporter
|
|
20
20
|
return unless concept_ai.concept.process?
|
21
21
|
|
22
22
|
file.write head(concept_ai.concept.name)
|
23
|
-
Application.instance.config[
|
23
|
+
Application.instance.config["questions"]["stages"].each do |stage|
|
24
24
|
concept_ai.questions[stage].each do |question|
|
25
25
|
file.write(QuestionGiftFormatter.to_s(question))
|
26
26
|
end
|
@@ -33,9 +33,9 @@ module ConceptAIGiftExporter
|
|
33
33
|
# @return String
|
34
34
|
private_class_method def self.head(name)
|
35
35
|
s = "\n"
|
36
|
-
s +=
|
36
|
+
s += "// " + "=" * 50 + "\n"
|
37
37
|
s += "// Concept name: #{name}\n"
|
38
|
-
s +=
|
38
|
+
s += "// " + "=" * 50 + "\n"
|
39
39
|
s
|
40
40
|
end
|
41
41
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require_relative
|
1
|
+
require "yaml"
|
2
|
+
require_relative "../formatter/question_hash_formatter"
|
3
3
|
|
4
4
|
# Use to export data from ConceptIA to YAML format
|
5
5
|
module ConceptAIYAMLExporter
|
@@ -12,11 +12,11 @@ module ConceptAIYAMLExporter
|
|
12
12
|
concepts_ai.each do |concept_ai|
|
13
13
|
questions += get_questions_from concept_ai
|
14
14
|
end
|
15
|
-
params = {
|
16
|
-
|
17
|
-
output = {
|
15
|
+
params = {lang: project.get(:lang),
|
16
|
+
projectname: project.get(:projectname)}
|
17
|
+
output = {params: params, questions: questions}
|
18
18
|
|
19
|
-
yamlfile = File.open(project.get(:yamlpath),
|
19
|
+
yamlfile = File.open(project.get(:yamlpath), "w")
|
20
20
|
yamlfile.write(output.to_yaml)
|
21
21
|
yamlfile.close
|
22
22
|
end
|
@@ -25,7 +25,7 @@ module ConceptAIYAMLExporter
|
|
25
25
|
data = []
|
26
26
|
return data unless concept_ai.concept.process?
|
27
27
|
|
28
|
-
Application.instance.config[
|
28
|
+
Application.instance.config["questions"]["stages"].each do |stage|
|
29
29
|
concept_ai.questions[stage].each do |question|
|
30
30
|
question.lang = concept_ai.concept.lang
|
31
31
|
data << QuestionHashFormatter.to_hash(question)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "../formatter/concept_doc_formatter"
|
4
|
+
require_relative "../version"
|
5
5
|
|
6
6
|
##
|
7
7
|
# Export Concept to Doc file
|
@@ -9,12 +9,12 @@ module ConceptDocExporter
|
|
9
9
|
##
|
10
10
|
# Export array of concepts to doc
|
11
11
|
def self.export_all(concepts, project)
|
12
|
-
file = File.new(project.get(:lessonpath),
|
13
|
-
file.write(
|
12
|
+
file = File.new(project.get(:lessonpath), "w")
|
13
|
+
file.write("=" * 50 + "\n")
|
14
14
|
file.write("Created by : #{Asker::NAME} (version #{Asker::VERSION})\n")
|
15
15
|
file.write("File : #{project.get(:lessonname)}\n")
|
16
16
|
file.write("Time : #{Time.new}\n")
|
17
|
-
file.write(
|
17
|
+
file.write("=" * 50 + "\n")
|
18
18
|
|
19
19
|
concepts.each do |concept|
|
20
20
|
file.write(ConceptDocFormatter.to_s(concept)) if concept.process
|