asker-tool 2.7.1 → 2.8.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 (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