asker-tool 2.6.0 → 2.7.0

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/lib/asker/ai/ai.rb +6 -6
  4. data/lib/asker/ai/ai_calculate.rb +3 -3
  5. data/lib/asker/ai/code/base_code_ai.rb +5 -30
  6. data/lib/asker/ai/code/code_ai_factory.rb +6 -12
  7. data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
  8. data/lib/asker/ai/code/python_code_ai.rb +35 -36
  9. data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
  10. data/lib/asker/ai/code/sql_code_ai.rb +20 -21
  11. data/lib/asker/ai/concept_ai.rb +12 -22
  12. data/lib/asker/ai/problem/problem_ai.rb +226 -0
  13. data/lib/asker/ai/question.rb +34 -45
  14. data/lib/asker/ai/stages/base_stage.rb +7 -7
  15. data/lib/asker/ai/stages/stage_b.rb +62 -28
  16. data/lib/asker/ai/stages/stage_d.rb +10 -10
  17. data/lib/asker/ai/stages/stage_f.rb +17 -17
  18. data/lib/asker/ai/stages/stage_i.rb +8 -18
  19. data/lib/asker/ai/stages/stage_s.rb +28 -26
  20. data/lib/asker/ai/stages/stage_t.rb +40 -51
  21. data/lib/asker/application.rb +15 -14
  22. data/lib/asker/check_input/check_haml_data.rb +52 -51
  23. data/lib/asker/check_input/check_table.rb +17 -20
  24. data/lib/asker/check_input.rb +10 -23
  25. data/lib/asker/cli.rb +43 -24
  26. data/lib/asker/data/code.rb +10 -9
  27. data/lib/asker/data/column.rb +21 -17
  28. data/lib/asker/data/concept.rb +24 -37
  29. data/lib/asker/data/data_field.rb +2 -2
  30. data/lib/asker/data/problem.rb +112 -0
  31. data/lib/asker/data/project_data.rb +11 -15
  32. data/lib/asker/data/row.rb +25 -23
  33. data/lib/asker/data/table.rb +25 -46
  34. data/lib/asker/data/template.rb +7 -7
  35. data/lib/asker/data/world.rb +3 -3
  36. data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
  37. data/lib/asker/displayer/code_displayer.rb +10 -10
  38. data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
  39. data/lib/asker/displayer/concept_ai_displayer.rb +16 -16
  40. data/lib/asker/displayer/concept_displayer.rb +4 -2
  41. data/lib/asker/displayer/problem_displayer.rb +45 -0
  42. data/lib/asker/displayer/stats_displayer.rb +7 -12
  43. data/lib/asker/exporter/code_gift_exporter.rb +2 -2
  44. data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
  45. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
  46. data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
  47. data/lib/asker/exporter/data_gift_exporter.rb +14 -15
  48. data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
  49. data/lib/asker/exporter/output_file_exporter.rb +9 -8
  50. data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
  51. data/lib/asker/files/language/ca/templates.yaml +6 -0
  52. data/lib/asker/files/language/du/templates.yaml +6 -0
  53. data/lib/asker/files/language/en/templates.yaml +7 -1
  54. data/lib/asker/files/language/es/templates.yaml +6 -0
  55. data/lib/asker/files/language/fr/templates.yaml +6 -0
  56. data/lib/asker/formatter/code_string_formatter.rb +5 -5
  57. data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
  58. data/lib/asker/formatter/concept_string_formatter.rb +6 -6
  59. data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
  60. data/lib/asker/formatter/moodle/gapfill.erb +57 -0
  61. data/lib/asker/formatter/moodle/ordering.erb +41 -0
  62. data/lib/asker/formatter/question_gift_formatter.rb +41 -14
  63. data/lib/asker/formatter/question_hash_formatter.rb +5 -6
  64. data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
  65. data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
  66. data/lib/asker/lang/lang.rb +16 -16
  67. data/lib/asker/lang/lang_factory.rb +13 -16
  68. data/lib/asker/lang/text_actions.rb +20 -18
  69. data/lib/asker/loader/code_loader.rb +10 -22
  70. data/lib/asker/loader/content_loader.rb +42 -49
  71. data/lib/asker/loader/directory_loader.rb +13 -16
  72. data/lib/asker/loader/embedded_file.rb +14 -14
  73. data/lib/asker/loader/file_loader.rb +5 -4
  74. data/lib/asker/loader/haml_loader.rb +4 -3
  75. data/lib/asker/loader/image_url_loader.rb +6 -5
  76. data/lib/asker/loader/input_loader.rb +24 -10
  77. data/lib/asker/loader/problem_loader.rb +88 -0
  78. data/lib/asker/loader/project_loader.rb +5 -12
  79. data/lib/asker/logger.rb +19 -10
  80. data/lib/asker/skeleton.rb +19 -35
  81. data/lib/asker/start.rb +44 -0
  82. data/lib/asker/version.rb +1 -1
  83. data/lib/asker.rb +7 -52
  84. metadata +12 -6
  85. data/lib/asker/ai/code/problem_code_ai.rb +0 -176
  86. data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
  87. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'row'
4
- require_relative 'template'
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 = { lang: true, type: true }
25
- @types = ['text'] * @fields.size
26
- @langs = [@concept.lang] * @fields.size
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 = (['text'] * @fields.size) if @types.nil?
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
- # read attributes from XML data
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['sequence']
76
+ return unless xml_data.attributes["sequence"]
84
77
 
85
- @sequence = xml_data.attributes['sequence'].to_s.split(',')
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 'lang'
84
+ when "lang"
98
85
  read_lang_from_xml(i)
99
- when 'row'
86
+ when "row"
100
87
  @datarows << Row.new(self, @datarows.size, i)
101
- when 'sequence'
102
- @sequence = i.text.split(',')
103
- when 'template'
88
+ when "sequence"
89
+ @sequence = i.text.split(",")
90
+ when "template"
104
91
  @datarows += Template.new(self, @datarows.size, i).datarows
105
- when 'type'
92
+ when "type"
106
93
  read_type_from_xml(i)
107
94
  else
108
- puts Rainbow("[ERROR] concept/table#xml_data with #{i.name}").red.bright
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(',') == codes.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 ['*', ''].include? k.strip
127
- @langs << @concept.lang
108
+ @langs << if ["*", ""].include? k.strip
109
+ @concept.lang
128
110
  else
129
- @langs << LangFactory.instance.get(k.strip.to_s)
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(',') == @types.join(',')
117
+ j = xml_data.text.split(",")
118
+ return if j.join(",") == @types.join(",")
140
119
 
141
120
  simple_off(:type)
142
121
  @types = []
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'rexml/document'
4
- require_relative 'row'
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 == 'mode'
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 == 'row'
60
+ if i.name == "row"
61
61
  datarows << Row.new(table, index, i)
62
62
  index += 1
63
63
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../loader/image_url_loader'
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 << c.context
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(' ').to_s }
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 = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
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 << ' <name>'
24
+ s << " <name>"
27
25
  s << " <text>#{question.name}</text>"
28
- s << ' </name>'
26
+ s << " </name>"
29
27
  s << ' <questiontext format="html">'
30
28
  s << " <text><![CDATA[#{question.text}]]></text>"
31
- s << ' </questiontext>'
29
+ s << " </questiontext>"
32
30
  s << ' <generalfeedback format="html">'
33
31
  s << " <text>#{question.feedback}</text>"
34
- s << ' </generalfeedback>'
35
- s << ' <defaultgrade>1.0000000</defaultgrade>'
32
+ s << " </generalfeedback>"
33
+ s << " <defaultgrade>1.0000000</defaultgrade>"
36
34
  s << " <penalty>#{penalty}</penalty>"
37
- s << ' <hidden>0</hidden>'
38
- s << ' <single>true</single>'
35
+ s << " <hidden>0</hidden>"
36
+ s << " <single>true</single>"
39
37
  s << " <shuffleanswers>#{question.shuffle?}</shuffleanswers>"
40
- s << ' <answernumbering>abc</answernumbering>'
38
+ s << " <answernumbering>abc</answernumbering>"
41
39
  s << ' <incorrectfeedback format="html">'
42
40
  s << " <text>#{question.feedback}</text>"
43
- s << ' </incorrectfeedback>'
41
+ s << " </incorrectfeedback>"
44
42
  s << ' <answer fraction="100" format="html">'
45
43
  s << " <text>#{question.good}</text>"
46
- s << ' </answer>'
44
+ s << " </answer>"
47
45
  s << ' <answer fraction="-25" format="html">'
48
46
  s << " <text>#{question.bad[0]}</text>"
49
- s << ' </answer>'
50
- s << ' </question>'
47
+ s << " </answer>"
48
+ s << " </question>"
51
49
  s << ' <answer fraction="-25" format="html">'
52
50
  s << " <text>#{question.bad[1]}</text>"
53
- s << ' </answer>'
54
- s << ' </question>'
51
+ s << " </answer>"
52
+ s << " </question>"
55
53
  s << ' <answer fraction="-25" format="html">'
56
54
  s << " <text>#{question.bad[2]}</text>"
57
- s << ' </answer>'
58
- s << ' </question>'
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 = 'Unkown'
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
- code.type,
26
- q,
27
- e,
28
- factor]
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
- Rainbow(total_q.to_s).bright,
38
- Rainbow(total_e.to_s).bright,
39
- Rainbow((total_q / total_e.to_f).round(2)).bright]
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 CODE statistics"
42
+ Logger.verboseln "\n[INFO] Showing CODEs statistics"
43
43
  Logger.verboseln my_screen_table.to_s
44
44
  end
45
45
  end
@@ -1,5 +1,5 @@
1
1
 
2
- [INFO] Showing CONCEPT statistics
2
+ [INFO] Showing CONCEPTs statistics
3
3
  * Exclude questions: <%= exclude_questions %>
4
4
  * Annotations:
5
5
  ├── (d) Definitions <= Concept.def
@@ -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
- t, e, factor, sd, sb, sf, si, ss, st]
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
- 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]]
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.verboseln "#{screen_table}\n"
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('Excluded questions').yellow.bright,
111
- total[:q], '-', '-',
112
- total[:sd], total[:sb],
113
- total[:sf], total[:si],
114
- total[:ss], total[:st]]
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['questions']['exclude'].to_s
119
- renderer = ERB.new(File.read(File.join(File.dirname(__FILE__), 'concept_ai_displayer.erb')))
120
- Logger.verboseln renderer.result(binding)
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
- s = "* Concepts (#{concepts.count}): "
18
- concepts.each { |c| s += c.name + ", " }
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 '../application'
4
- require_relative 'concept_ai_displayer'
5
- require_relative 'code_displayer'
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
- # Display Stats on screen.
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['global']['show_mode']
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 += '// ' + '=' * 50 + "\n"
26
+ s += "// " + "=" * 50 + "\n"
27
27
  s += "// Code #{code.type}: #{code.filename} (#{code.questions.size})\n"
28
- s += '// ' + '=' * 50 + "\n"
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 '../formatter/question_gift_formatter'
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['questions']['stages'].each do |stage|
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 += '// ' + '=' * 50 + "\n"
36
+ s += "// " + "=" * 50 + "\n"
37
37
  s += "// Concept name: #{name}\n"
38
- s += '// ' + '=' * 50 + "\n"
38
+ s += "// " + "=" * 50 + "\n"
39
39
  s
40
40
  end
41
41
  end
@@ -1,5 +1,5 @@
1
- require 'yaml'
2
- require_relative '../formatter/question_hash_formatter'
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 = { lang: project.get(:lang) ,
16
- projectname: project.get(:projectname) }
17
- output = { params: params, questions: questions }
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), 'w')
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['questions']['stages'].each do |stage|
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 '../formatter/concept_doc_formatter'
4
- require_relative '../version'
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), 'w')
13
- file.write('=' * 50 + "\n")
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('=' * 50 + "\n")
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 'concept_ai_gift_exporter'
4
- require_relative 'code_gift_exporter'
5
- require_relative '../version'
6
- require_relative '../application'
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 (ConceptAI and Code objects) into GIFT outpufile
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), 'w')
16
- file.write('// ' + ('=' * 50) + "\n")
17
- file.write("// Created by : #{Asker::NAME}")
18
- file.write(" (version #{Asker::VERSION})\n")
19
- file.write("// File : #{project.get(:outputname)}\n")
20
- file.write("// Time : #{Time.new}\n")
21
- file.write('// ' + ('=' * 50) + "\n\n")
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