asker-tool 2.7.1 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asker/ai/problem/customizer.rb +36 -0
  3. data/lib/asker/ai/problem/problem_ai.rb +9 -213
  4. data/lib/asker/ai/problem/stage_answers.rb +104 -0
  5. data/lib/asker/ai/problem/stage_base.rb +34 -0
  6. data/lib/asker/ai/problem/stage_steps.rb +121 -0
  7. data/lib/asker/application.rb +1 -0
  8. data/lib/asker/check_input/check_haml_data.rb +136 -0
  9. data/lib/asker/check_input.rb +15 -10
  10. data/lib/asker/cli.rb +2 -0
  11. data/lib/asker/data/concept.rb +3 -3
  12. data/lib/asker/data/problem.rb +10 -2
  13. data/lib/asker/data/project_data.rb +2 -1
  14. data/lib/asker/displayer/code_displayer.rb +2 -2
  15. data/lib/asker/displayer/concept_ai_displayer.rb +5 -3
  16. data/lib/asker/displayer/concept_displayer.rb +2 -2
  17. data/lib/asker/displayer/problem_displayer.rb +14 -7
  18. data/lib/asker/displayer/stats_displayer.rb +3 -3
  19. data/lib/asker/files/language/ca/templates.yaml +1 -0
  20. data/lib/asker/files/language/du/templates.yaml +1 -0
  21. data/lib/asker/files/language/en/templates.yaml +1 -0
  22. data/lib/asker/files/language/es/templates.yaml +1 -0
  23. data/lib/asker/files/language/fr/templates.yaml +1 -0
  24. data/lib/asker/formatter/concept_string_formatter.rb +0 -1
  25. data/lib/asker/loader/content_loader.rb +10 -8
  26. data/lib/asker/loader/embedded_file/loader.rb +103 -0
  27. data/lib/asker/loader/embedded_file/type.rb +51 -0
  28. data/lib/asker/loader/file_loader.rb +2 -1
  29. data/lib/asker/loader/problem_loader.rb +2 -0
  30. data/lib/asker/logger.rb +7 -3
  31. data/lib/asker/start.rb +2 -2
  32. data/lib/asker/version.rb +1 -1
  33. metadata +8 -3
  34. data/lib/asker/loader/embedded_file.rb +0 -133
@@ -2,34 +2,39 @@ require_relative "check_input/check_haml_data"
2
2
  require_relative "logger"
3
3
 
4
4
  class CheckInput
5
+ attr_accessor :verbose
6
+
7
+ def initialize
8
+ @verbose = true
9
+ end
10
+
5
11
  def check(filepath)
6
- @filepath = filepath
7
12
  # Check HAML file syntax
8
- exist = check_file_exist
13
+ exist = check_file_exist(filepath)
9
14
  return false unless exist
10
- check_file_content
15
+ check_file_content(filepath)
11
16
  end
12
17
 
13
18
  private
14
19
 
15
- def check_file_exist
16
- if @filepath.nil?
20
+ def check_file_exist(filepath)
21
+ if filepath.nil?
17
22
  Logger.error "CheckInput: Unknown filename"
18
23
  exit 1
19
24
  end
20
- unless File.exist? @filepath
21
- Logger.error "CheckInput: File not found! (#{@filepath})"
25
+ unless File.exist? filepath
26
+ Logger.error "CheckInput: File not found! (#{filepath})"
22
27
  exit 1
23
28
  end
24
- unless File.extname(@filepath) == ".haml"
29
+ unless File.extname(filepath) == ".haml"
25
30
  Logger.error "CheckInput: Check works with HAML files!"
26
31
  exit 1
27
32
  end
28
33
  true
29
34
  end
30
35
 
31
- def check_file_content
32
- data = CheckHamlData.new(@filepath)
36
+ def check_file_content(filepath)
37
+ data = CheckHamlData.new(filepath)
33
38
  data.check
34
39
  data.show_errors if @verbose
35
40
  data.ok?
data/lib/asker/cli.rb CHANGED
@@ -45,6 +45,7 @@ class CLI < Thor
45
45
  end
46
46
 
47
47
  map ["--check"] => "check"
48
+ option :color, type: :boolean
48
49
  desc "check FILEPATH", "Check HAML input file syntax"
49
50
  long_desc <<-LONGDESC
50
51
 
@@ -64,6 +65,7 @@ class CLI < Thor
64
65
  end
65
66
 
66
67
  map ["f", "-f", "--file"] => "file"
68
+ option :color, type: :boolean
67
69
  desc "[file] FILEPATH", "Build output files, from HAML/XML input file."
68
70
  long_desc <<-LONGDESC
69
71
 
@@ -1,7 +1,7 @@
1
1
  require "rexml/document"
2
2
 
3
3
  require_relative "../lang/lang_factory"
4
- require_relative "../loader/embedded_file"
4
+ require_relative "../loader/embedded_file/loader"
5
5
  require_relative "../logger"
6
6
  require_relative "table"
7
7
  require_relative "data_field"
@@ -173,10 +173,10 @@ class Concept
173
173
  case value.attributes["type"]
174
174
  when "image_url"
175
175
  # Link with remote image
176
- @data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
176
+ @data[:images] << EmbeddedFile::Loader.new.call(value.text.strip, File.dirname(@filename))
177
177
  when "file"
178
178
  # Load local images and text files
179
- @data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
179
+ @data[:images] << EmbeddedFile::Loader.new.call(value.text.strip, File.dirname(@filename))
180
180
  when nil
181
181
  if value.text.nil?
182
182
  Logger.warn "Concept: def/text empty!"
@@ -1,4 +1,5 @@
1
1
  require_relative "../logger"
2
+ require_relative "../lang/lang_factory"
2
3
 
3
4
  class Problem
4
5
  attr_accessor :lang
@@ -10,12 +11,13 @@ class Problem
10
11
  attr_accessor :descs
11
12
  attr_accessor :asks
12
13
  attr_accessor :questions
14
+ attr_accessor :stats
13
15
 
14
16
  @@id = 0
15
17
  def initialize
16
18
  @@id += 1
17
19
  @id = @@id
18
- @lang = nil
20
+ @lang = LangFactory.instance.get("en")
19
21
  @context = nil
20
22
  @process = false
21
23
  @filename = "?"
@@ -24,6 +26,7 @@ class Problem
24
26
  @descs = []
25
27
  @asks = []
26
28
  @questions = []
29
+ @stats = { answer: 0, steps: 0}
27
30
  end
28
31
 
29
32
  def self.from(values)
@@ -46,7 +49,8 @@ class Problem
46
49
  end
47
50
 
48
51
  def name
49
- "problem#{@id}"
52
+ firstword = @descs[0]&.strip&.split(" ")&.first&.downcase || "problem"
53
+ "#{firstword}#{@id}"
50
54
  end
51
55
 
52
56
  def validate
@@ -59,6 +63,8 @@ class Problem
59
63
  private
60
64
 
61
65
  def validate_varnames
66
+ return if @varnames.nil?
67
+
62
68
  if !@varnames.size.zero? && @cases.size.zero?
63
69
  Logger.warn "Problem: No problem/varnames defined with no problem/case"
64
70
  end
@@ -75,6 +81,8 @@ class Problem
75
81
  end
76
82
 
77
83
  def validate_cases
84
+ return if @cases.nil?
85
+
78
86
  @cases.each do |acase|
79
87
  if acase.size != @varnames.size
80
88
  Logger.error "Problem: problem/cases size not equal to problem/varnames size"
@@ -11,7 +11,8 @@ class ProjectData
11
11
  end
12
12
 
13
13
  def reset
14
- @default = {inputbasedir: FileUtils.pwd,
14
+ # @default = {inputbasedir: FileUtils.pwd,
15
+ @default = {inputbasedir: Dir.pwd,
15
16
  stages: {d: true, b: true, f: true, i: true, s: true, t: true},
16
17
  threshold: 0.5,
17
18
  outputdir: "output",
@@ -1,11 +1,11 @@
1
1
  require "terminal-table"
2
2
  require_relative "../logger"
3
3
 
4
- module CodeDisplayer
4
+ class CodeDisplayer
5
5
  ##
6
6
  # Show all "code" data on screen
7
7
  # @param codes (Array) List of "code" data
8
- def self.show(codes)
8
+ def call(codes)
9
9
  return if codes.nil? || codes.size.zero?
10
10
 
11
11
  total_c = total_q = total_e = 0
@@ -10,7 +10,7 @@ class ConceptAIDisplayer
10
10
  ##
11
11
  # Display ConceptAI stat on screen
12
12
  # @param concepts_ai (Array)
13
- def self.show(concepts_ai)
13
+ def call(concepts_ai)
14
14
  stages = Application.instance.config["questions"]["stages"]
15
15
  # Create table HEAD
16
16
  screen_table = Terminal::Table.new do |st|
@@ -80,7 +80,9 @@ class ConceptAIDisplayer
80
80
  Logger.info "#{screen_table}\n"
81
81
  end
82
82
 
83
- private_class_method def self.export_excluded_questions(screen_table, concepts_ai)
83
+ private
84
+
85
+ def export_excluded_questions(screen_table, concepts_ai)
84
86
  # Create table BODY
85
87
  total = {}
86
88
  total[:q] = total[:c] = 0
@@ -114,7 +116,7 @@ class ConceptAIDisplayer
114
116
  total[:ss], total[:st]]
115
117
  end
116
118
 
117
- private_class_method def self.export_notes
119
+ def export_notes
118
120
  exclude_questions = Application.instance.config["questions"]["exclude"].to_s
119
121
  renderer = ERB.new(File.read(File.join(File.dirname(__FILE__), "concept_ai_displayer.erb")))
120
122
  Logger.info Rainbow(renderer.result(binding)).white
@@ -2,11 +2,11 @@ require_relative "../application"
2
2
  require_relative "../formatter/concept_string_formatter"
3
3
  require_relative "../logger"
4
4
 
5
- module ConceptDisplayer
5
+ class ConceptDisplayer
6
6
  ##
7
7
  # Show concepts on screen
8
8
  # @param concepts (Array) List of concept data
9
- def self.show(concepts)
9
+ def call(concepts)
10
10
  return if concepts.nil? || concepts.size.zero?
11
11
 
12
12
  show_mode = Application.instance.config["global"]["show_mode"]
@@ -1,16 +1,16 @@
1
1
  require "terminal-table"
2
2
  require_relative "../logger"
3
3
 
4
- module ProblemDisplayer
4
+ class ProblemDisplayer
5
5
  ##
6
6
  # Show all "problem" data on screen
7
7
  # @param problems (Array) List of "problems" data
8
- def self.show(problems)
8
+ def call(problems)
9
9
  return if problems.nil? || problems.size.zero?
10
10
 
11
- total_p = total_q = total_e = 0
11
+ total_p = total_q = total_e = total_a = total_s = 0
12
12
  my_screen_table = Terminal::Table.new do |st|
13
- st << %w[Problem Desc Questions Entries xFactor]
13
+ st << %w[Problem Desc Questions Entries xFactor a s]
14
14
  st << :separator
15
15
  end
16
16
 
@@ -23,14 +23,19 @@ module ProblemDisplayer
23
23
  e += 1 if !ask[:answer].nil?
24
24
  end
25
25
 
26
+ desc = Rainbow(problem.desc[0, 24]).green
26
27
  q = problem.questions.size
27
28
  factor = "Unknown"
28
29
  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]
30
+ a = problem.stats[:answer]
31
+ s = problem.stats[:steps]
32
+
33
+ my_screen_table.add_row [problem.name, desc, q, e, factor, a, s]
31
34
  total_p += 1
32
35
  total_q += q
33
36
  total_e += e
37
+ total_a += a
38
+ total_s += s
34
39
  end
35
40
  return unless total_p.positive?
36
41
 
@@ -38,7 +43,9 @@ module ProblemDisplayer
38
43
  my_screen_table.add_row [Rainbow("TOTAL = #{total_p}").bright, "",
39
44
  Rainbow(total_q.to_s).bright,
40
45
  Rainbow(total_e.to_s).bright,
41
- Rainbow((total_q / total_e.to_f).round(2)).bright]
46
+ Rainbow((total_q / total_e.to_f).round(2)).bright,
47
+ Rainbow(total_a.to_s).bright,
48
+ Rainbow(total_s.to_s).bright]
42
49
  Logger.verboseln Rainbow("\n[INFO] Showing PROBLEMs statistics").white
43
50
  Logger.verboseln my_screen_table.to_s
44
51
  end
@@ -10,8 +10,8 @@ module StatsDisplayer
10
10
  def self.show(data)
11
11
  return unless Application.instance.config["global"]["show_mode"]
12
12
 
13
- ConceptAIDisplayer.show(data[:concepts_ai])
14
- CodeDisplayer.show(data[:codes_ai])
15
- ProblemDisplayer.show(data[:problems])
13
+ ConceptAIDisplayer.new.call(data[:concepts_ai])
14
+ CodeDisplayer.new.call(data[:codes_ai])
15
+ ProblemDisplayer.new.call(data[:problems])
16
16
  end
17
17
  end
@@ -33,3 +33,4 @@
33
33
  :ps4: 'Canvia el pas <%=text1%> pel pas <%=text2%>'
34
34
  :ps5: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Resposta:</b ></p><pre><%=text3%></pre><br/><i>(Col·loca cada pas en la seva posició correcta dins de la seqüència)</i>'
35
35
  :ps6: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><br/><i>(Posa cada pas en la posició correcta dins de la seqüència)</i>'
36
+ :ps7: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Resposta:</b ></p><pre><%=text3%></pre><br/><i>(Nota: Cada símbol ? representa una lletra/símbol, i cada * represent una o diverses paraules.)</i >'
@@ -33,3 +33,4 @@
33
33
  :ps4: 'Ändere Schritt <%=text1%> in Schritt <%=text2%>'
34
34
  :ps5: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><p><b>Antwort:</b ></p><pre><%=text3%></pre><br/><i>(Platzieren Sie jeden Schritt an der richtigen Position innerhalb der Sequenz)</i>'
35
35
  :ps6: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><br/><i>(Platzieren Sie jeden Schritt an der richtigen Position innerhalb der Sequenz)</i>'
36
+ :ps7: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><p><b>Antwort:</b ></p><pre><%=text3%></pre><br/><i>(Hinweis: Jedes ? steht für einen Buchstaben/ein Symbol und jedes * steht für ein oder mehrere Wörter.)</i > '
@@ -33,3 +33,4 @@
33
33
  :ps4: 'Change step <%=text1%> by step <%=text2%>'
34
34
  :ps5: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><p><b>Answer:</b></p><pre><%=text3%></pre><br/><i>(Place each step in its correct position within the sequence)</i>'
35
35
  :ps6: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><br/><i>(Place each step in its correct position within the sequence)</i>'
36
+ :ps7: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><p><b>Answer:</b ></p><pre><%=text3%></pre><br/><i>(Note: Each ? represents a letter/symbol, and each * represents one or more words.)</i>'
@@ -33,3 +33,4 @@
33
33
  :ps4: 'Cambia el paso <%=text1%> por el paso <%=text2%>'
34
34
  :ps5: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Respuesta:</b></p><pre><%=text3%></pre><br/><i>(Coloca cada paso en su posición correcta dentro de la secuencia)</i>'
35
35
  :ps6: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><br/><i>(Coloca cada paso en su posición correcta dentro de la secuencia)</i>'
36
+ :ps7: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Respuesta:</b></p><pre><%=text3%></pre><br/><i>(Nota: Cada símbolo ? representa una letra/símbolo, y cada * represent una o varias palabras.)</i>'
@@ -33,3 +33,4 @@
33
33
  :ps4: "Changer l'étape <%=text1%> en étape <%=text2%>"
34
34
  :ps5 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><p><b>Réponse :</b ></p><pre><%=text3%></pre><br/><i>(Placez chaque étape dans sa position correcte dans la séquence)</i>"
35
35
  :ps6 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><br/><i>(Placez chaque étape dans sa position correcte dans la séquence)</i>"
36
+ :ps7 : '<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><p><b>Réponse :</b ></p><pre><%=text3%></pre><br/><i>(Remarque : chaque ? représente une lettre/un symbole, et chaque * représente un ou plusieurs mots.)</i > '
@@ -3,7 +3,6 @@
3
3
  require "rainbow"
4
4
  require "terminal-table"
5
5
 
6
- # Define methods to transform Concept into String
7
6
  module ConceptStringFormatter
8
7
  ##
9
8
  # Formatter Concept to String
@@ -6,12 +6,12 @@ require_relative "../data/project_data"
6
6
  require_relative "../lang/lang_factory"
7
7
  require_relative "../logger"
8
8
 
9
- module ContentLoader
9
+ class ContentLoader
10
10
  ##
11
11
  # Load XML content into Asker data objects
12
12
  # @param filepath (String) File path
13
13
  # @param content (String) XML plane text content
14
- def self.call(filepath, content)
14
+ def call(filepath, content)
15
15
  begin
16
16
  xmlcontent = REXML::Document.new(content)
17
17
  rescue REXML::ParseException
@@ -39,7 +39,9 @@ module ContentLoader
39
39
  {concepts: concepts, codes: codes, problems: problems}
40
40
  end
41
41
 
42
- private_class_method def self.read_lang_attribute(xmldata)
42
+ private
43
+
44
+ def read_lang_attribute(xmldata)
43
45
  begin
44
46
  lang_code = xmldata.root.attributes["lang"]
45
47
  rescue itself
@@ -49,7 +51,7 @@ module ContentLoader
49
51
  LangFactory.instance.get(lang_code)
50
52
  end
51
53
 
52
- private_class_method def self.read_context_attribute(xmldata)
54
+ def read_context_attribute(xmldata)
53
55
  begin
54
56
  context = xmldata.root.attributes["context"].split(",")
55
57
  context.collect!(&:strip)
@@ -60,7 +62,7 @@ module ContentLoader
60
62
  context
61
63
  end
62
64
 
63
- private_class_method def self.read_concept(xmldata, filepath, lang, context)
65
+ def read_concept(xmldata, filepath, lang, context)
64
66
  project = ProjectData.instance
65
67
  concept = Concept.new(xmldata, filepath, lang, context)
66
68
  cond = [File.basename(filepath), :default].include? project.get(:process_file)
@@ -68,7 +70,7 @@ module ContentLoader
68
70
  concept
69
71
  end
70
72
 
71
- private_class_method def self.read_code(xmldata, filepath)
73
+ def read_code(xmldata, filepath)
72
74
  project = ProjectData.instance
73
75
  code = CodeLoader.call(xmldata, filepath)
74
76
  cond = [File.basename(filepath), :default].include? project.get(:process_file)
@@ -76,7 +78,7 @@ module ContentLoader
76
78
  code
77
79
  end
78
80
 
79
- private_class_method def self.read_problem(xmldata, filepath, lang, context)
81
+ def read_problem(xmldata, filepath, lang, context)
80
82
  project = ProjectData.instance
81
83
  problem = ProblemLoader.new(lang, context).call(xmldata, filepath)
82
84
  cond = [File.basename(filepath), :default].include? project.get(:process_file)
@@ -84,7 +86,7 @@ module ContentLoader
84
86
  problem
85
87
  end
86
88
 
87
- private_class_method def self.raise_error_with(filepath, content)
89
+ def raise_error_with(filepath, content)
88
90
  Logger.error "ContentLoader: Format error (#{filepath})"
89
91
  Logger.error " : Revise output file (ouput/error.xml)"
90
92
  f = File.open("output/error.xml", "w")
@@ -0,0 +1,103 @@
1
+ require "base64"
2
+ require_relative "../../logger"
3
+ require_relative "type"
4
+
5
+ module EmbeddedFile
6
+ # Methods to load embedded files defined into asker input data file
7
+ # Examples:
8
+ # def line with :type = :image_url used to link external file as https://..."
9
+ # def line with :type = :file used to load local file as image.png or file.txt"
10
+ class Loader
11
+ ##
12
+ # @param value (String)
13
+ # @param localdir (String) Input file base folder
14
+ # @return Hash
15
+ def call(value, localdir)
16
+ filepath = File.join(localdir, value)
17
+ type = EmbebbedFile::Type.new.for(value, localdir)
18
+
19
+ case type
20
+ when :image
21
+ return load_image(value, localdir)
22
+ when :image_url
23
+ return load_image_url(value, localdir)
24
+ when :audio
25
+ return load_audio(value, localdir)
26
+ when :audio_url
27
+ return load_audio_url(value, localdir)
28
+ when :video
29
+ return load_video(value, localdir)
30
+ when :video_url
31
+ return load_video_url(value, localdir)
32
+ end
33
+
34
+ {text: "<pre>#{File.read(filepath)}</pre>", file: :none, type: :text}
35
+ end
36
+
37
+ def load_audio(value, localdir)
38
+ filepath = File.join(localdir, value)
39
+ output = {}
40
+ output[:text] = '<audio controls><source src="@@PLUGINFILE@@/' + File.basename(filepath) \
41
+ + '">Your browser does not support the audio tag.</audio>'
42
+ output[:file] = '<file name="' + File.basename(filepath) \
43
+ + '" path="/" encoding="base64">' \
44
+ + Base64.strict_encode64(File.open(filepath, "rb").read) \
45
+ + "</file>"
46
+ output[:type] = :audio
47
+ output
48
+ end
49
+
50
+ def load_audio_url(value, localdir)
51
+ {
52
+ text: "<audio src=\"#{value}\" controls></audio>",
53
+ file: :none,
54
+ type: :url
55
+ }
56
+ end
57
+
58
+ def load_image(value, localdir)
59
+ filepath = File.join(localdir, value)
60
+ output = {}
61
+ output[:text] = '<img src="@@PLUGINFILE@@/' + File.basename(filepath) \
62
+ + '" alt="imagen" class="img-responsive atto_image_button_text-bottom">'
63
+ output[:file] = '<file name="' + File.basename(filepath) \
64
+ + '" path="/" encoding="base64">' \
65
+ + Base64.strict_encode64(File.open(filepath, "rb").read) \
66
+ + "</file>"
67
+ output[:type] = :image
68
+ output
69
+ end
70
+
71
+ def load_image_url(value, localdir)
72
+ {
73
+ text: "<img src=\"#{value}\" alt=\"image\" width=\"400\" height=\"300\">",
74
+ file: :none,
75
+ type: :url
76
+ }
77
+ end
78
+
79
+ def load_video(value, localdir)
80
+ filepath = File.join(localdir, value)
81
+ output = {}
82
+ output[:text] = '<video controls><source src="@@PLUGINFILE@@/' \
83
+ + File.basename(filepath) \
84
+ + '"/>Your browser does not support the video tag.</video>'
85
+ output[:file] = '<file name="' \
86
+ + File.basename(filepath) \
87
+ + '" path="/" encoding="base64">' \
88
+ + Base64.strict_encode64(File.open(filepath, "rb").read) \
89
+ + "</file>"
90
+ output[:type] = :video
91
+ output
92
+ end
93
+
94
+ def load_video_url(value, localdir)
95
+ {
96
+ text: "<video controls width=\"400\" height=\"300\">" \
97
+ + "<source src=\"#{value}\"/></video>",
98
+ file: :none,
99
+ type: :url
100
+ }
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,51 @@
1
+
2
+ module EmbebbedFile
3
+ class Type
4
+ def for(value, localdir)
5
+ if is_url? value
6
+ return :image_url if is_image? value
7
+ return :audio_url if is_audio? value
8
+ return :video_url if is_video? value
9
+
10
+ Logger.error "EmbebbedFile::Type.for: Unknown URL type (#{value})"
11
+ exit 1
12
+ end
13
+
14
+ filepath = File.join(localdir, value)
15
+ unless File.exist?(filepath)
16
+ Logger.error "EmbeddedFile::Type.for: File does not exist (#{filepath})"
17
+ exit 1
18
+ end
19
+
20
+ return :image if is_image? value
21
+ return :audio if is_audio? value
22
+ return :video if is_video? value
23
+
24
+ :text
25
+ end
26
+
27
+ def is_audio?(filename)
28
+ extens = [".mp3", ".ogg", ".wav"]
29
+ extens.each { |ext| return true if filename.downcase.end_with?(ext) }
30
+ false
31
+ end
32
+
33
+ def is_image?(filename)
34
+ extens = [".jpg", ".jpeg", ".png"]
35
+ extens.each { |ext| return true if filename.downcase.end_with?(ext) }
36
+ false
37
+ end
38
+
39
+ def is_video?(filename)
40
+ extens = [".mp4", ".ogv"]
41
+ extens.each { |ext| return true if filename.downcase.end_with?(ext) }
42
+ false
43
+ end
44
+
45
+ def is_url?(value)
46
+ return true if value.start_with?("https://", "http://")
47
+
48
+ false
49
+ end
50
+ end
51
+ end
@@ -7,6 +7,7 @@ require_relative "../logger"
7
7
  # return { concepts: [], codes: [] }
8
8
  module FileLoader
9
9
  def self.call(filename)
10
+ Logger.debug "==> Loading #{filename}"
10
11
  if File.extname(filename).casecmp(".haml").zero?
11
12
  file_content = HamlLoader.load filename
12
13
  elsif File.extname(filename).casecmp(".xml").zero?
@@ -15,6 +16,6 @@ module FileLoader
15
16
  Logger.error "FileLoader: HAML or XML required (#{filename})"
16
17
  exit 1
17
18
  end
18
- ContentLoader.call(filename, file_content)
19
+ ContentLoader.new.call(filename, file_content)
19
20
  end
20
21
  end
@@ -64,6 +64,8 @@ class ProblemLoader
64
64
  ask[:text] = i.text
65
65
  elsif i.name == "answer"
66
66
  ask[:answer] = i.text
67
+ type = i.attributes["type"]
68
+ ask[:answer_type] = type unless type.nil?
67
69
  elsif i.name == "step"
68
70
  ask[:steps] << i.text
69
71
  else
data/lib/asker/logger.rb CHANGED
@@ -1,14 +1,18 @@
1
- require "singleton"
2
1
  require_relative "version"
3
2
 
4
3
  class Logger
5
- include Singleton
6
4
  @verbose = true
7
5
 
8
- def set_verbose(value)
6
+ def self.set_verbose(value)
9
7
  @verbose = (value == "yes")
10
8
  end
11
9
 
10
+ def self.debug(msg)
11
+ msg = Rainbow("#{msg}").white
12
+ puts msg if @verbose
13
+ @logfile&.write(msg)
14
+ end
15
+
12
16
  def self.info(msg)
13
17
  puts msg if @verbose
14
18
  @logfile&.write(msg)
data/lib/asker/start.rb CHANGED
@@ -9,7 +9,7 @@ require_relative "loader/input_loader"
9
9
  class Start
10
10
  def call(filepath)
11
11
  project_data, data = load_input(filepath)
12
- ConceptDisplayer.show(data[:concepts])
12
+ ConceptDisplayer.new.call(data[:concepts])
13
13
  create_output(project_data, data)
14
14
  end
15
15
 
@@ -19,7 +19,7 @@ class Start
19
19
  init_project_data
20
20
  project_data = ProjectLoader.load(args)
21
21
  Logger.create(project_data.get(:logpath))
22
- Logger.instance.set_verbose(Application.instance.config["verbose"])
22
+ Logger.set_verbose(Application.instance.config["global"]["verbose"])
23
23
 
24
24
  inputdirs = project_data.get(:inputdirs).split(",")
25
25
  internet = Application.instance.config["global"]["internet"] == "yes"
data/lib/asker/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Asker
2
- VERSION = "2.7.1"
2
+ VERSION = "2.8.0"
3
3
  NAME = "asker"
4
4
  GEM = "asker-tool"
5
5
  CONFIGFILE = "asker.ini"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asker-tool
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Vargas Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-23 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -117,7 +117,11 @@ files:
117
117
  - lib/asker/ai/code/ruby_code_ai.rb
118
118
  - lib/asker/ai/code/sql_code_ai.rb
119
119
  - lib/asker/ai/concept_ai.rb
120
+ - lib/asker/ai/problem/customizer.rb
120
121
  - lib/asker/ai/problem/problem_ai.rb
122
+ - lib/asker/ai/problem/stage_answers.rb
123
+ - lib/asker/ai/problem/stage_base.rb
124
+ - lib/asker/ai/problem/stage_steps.rb
121
125
  - lib/asker/ai/question.rb
122
126
  - lib/asker/ai/stages/base_stage.rb
123
127
  - lib/asker/ai/stages/main.rb
@@ -210,7 +214,8 @@ files:
210
214
  - lib/asker/loader/code_loader.rb
211
215
  - lib/asker/loader/content_loader.rb
212
216
  - lib/asker/loader/directory_loader.rb
213
- - lib/asker/loader/embedded_file.rb
217
+ - lib/asker/loader/embedded_file/loader.rb
218
+ - lib/asker/loader/embedded_file/type.rb
214
219
  - lib/asker/loader/file_loader.rb
215
220
  - lib/asker/loader/haml_loader.rb
216
221
  - lib/asker/loader/image_url_loader.rb