asker-tool 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -4
- 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 +16 -16
- 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 = "Unkown"
|
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
|
@@ -51,7 +51,7 @@ class ConceptAIDisplayer
|
|
51
51
|
factor = "Unkown"
|
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 = "Unkown"
|
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
|
@@ -1,30 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require_relative "concept_ai_gift_exporter"
|
4
|
+
require_relative "code_gift_exporter"
|
5
|
+
require_relative "problem_gift_exporter"
|
6
|
+
require_relative "../application"
|
7
|
+
require_relative "../version"
|
7
8
|
|
8
|
-
# Export Data (ConceptIA and Code) to gift to outputfile
|
9
9
|
module DataGiftExporter
|
10
10
|
##
|
11
|
-
# Export an array of Data (
|
11
|
+
# Export an array of Data (ConceptAIs, Codes and Problems objects) into GIFT file
|
12
12
|
# @param data (Hash)
|
13
13
|
# @param project (Project)
|
14
14
|
def self.export_all(data, project)
|
15
|
-
file = File.open(project.get(:outputpath),
|
16
|
-
file.write(
|
17
|
-
file.write("//
|
18
|
-
file.write("
|
19
|
-
file.write("//
|
20
|
-
file.write("//
|
21
|
-
|
22
|
-
category = Application.instance.config['questions']['category']
|
15
|
+
file = File.open(project.get(:outputpath), "w")
|
16
|
+
file.write("// " + ("=" * 50) + "\n")
|
17
|
+
file.write("// #{Asker::NAME} : version #{Asker::VERSION}\n")
|
18
|
+
file.write("// Filename : #{project.get(:outputname)}\n")
|
19
|
+
file.write("// Datetime : #{Time.new}\n")
|
20
|
+
file.write("// " + ("=" * 50) + "\n\n")
|
21
|
+
category = Application.instance.config["questions"]["category"]
|
23
22
|
file.write("$CATEGORY: $course$/#{category}\n") unless category.nil?
|
24
23
|
|
25
24
|
ConceptAIGiftExporter.export_all(data[:concepts_ai], file)
|
26
25
|
CodeGiftExporter.export_all(data[:codes_ai], file)
|
27
|
-
|
26
|
+
ProblemGiftExporter.new.call(data[:problems], file)
|
28
27
|
file.close
|
29
28
|
end
|
30
29
|
end
|