asker-tool 2.8.0 → 2.9.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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asker/data/concept.rb +2 -2
  3. data/lib/asker/data/project_data.rb +1 -1
  4. data/lib/asker/exporter/doc/format_code2doc.rb +17 -0
  5. data/lib/asker/exporter/doc/format_concept2doc.rb +30 -0
  6. data/lib/asker/exporter/doc/format_problem2doc.rb +41 -0
  7. data/lib/asker/exporter/export2doc.rb +41 -0
  8. data/lib/asker/exporter/{data_gift_exporter.rb → export2gift.rb} +8 -8
  9. data/lib/asker/exporter/{data_moodle_exporter.rb → export2moodle_xml.rb} +13 -11
  10. data/lib/asker/exporter/export2yaml.rb +70 -0
  11. data/lib/asker/exporter/export_action.rb +18 -0
  12. data/lib/asker/exporter/{code_gift_exporter.rb → gift/export_code2gift.rb} +7 -6
  13. data/lib/asker/exporter/{concept_ai_gift_exporter.rb → gift/export_concept2gift.rb} +7 -8
  14. data/lib/asker/exporter/{problem_gift_exporter.rb → gift/export_problem2gift.rb} +2 -2
  15. data/lib/asker/{formatter → exporter/gift}/question_gift_formatter.rb +0 -3
  16. data/lib/asker/formatter/{question_hash_formatter.rb → question2hash.rb} +15 -7
  17. data/lib/asker/formatter/{question_moodle_formatter.rb → question2moodle_xml.rb} +3 -5
  18. data/lib/asker/loader/code_loader.rb +1 -1
  19. data/lib/asker/loader/content_loader.rb +1 -0
  20. data/lib/asker/loader/embedded_file/loader.rb +15 -4
  21. data/lib/asker/logger.rb +1 -1
  22. data/lib/asker/start.rb +2 -2
  23. data/lib/asker/version.rb +1 -1
  24. metadata +16 -15
  25. data/lib/asker/deprecated/question_moodlexml_formatter.rb +0 -69
  26. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +0 -36
  27. data/lib/asker/exporter/concept_doc_exporter.rb +0 -24
  28. data/lib/asker/exporter/output_file_exporter.rb +0 -18
  29. data/lib/asker/formatter/concept_doc_formatter.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a70a91ae23f461cc6740e7938555a205ca50fa9f7b910a6af4e4d6b873ff3ba1
4
- data.tar.gz: 79a7f6dccf7faea3bc97b7e21b2bc5680d52b887b0aaa3eef52a6c0302f9d5ed
3
+ metadata.gz: cb6924c54cad0b4b8a04231d21f5b4e5e419f2150f6457b080eaa56ec45fc5bb
4
+ data.tar.gz: d6fac1e84e3e4c7f1e836acac9a050fd36b300960e122e993f4af676905b8aaa
5
5
  SHA512:
6
- metadata.gz: d87d28ecb0899a1f37fe791e0a08057e4b5dbba966202dc2111b339d34e4cc063a000b87436fa5e864320d366c245216123bffed9b9b7848c838a95fb3b9f845
7
- data.tar.gz: 9fe5684a838726523be099358f604e5ed5838c083a1043577cb9e445cba32e733f89e0dc98c4fa2408f37bab1909f523211a20d5820dd9743565f0435a11df87
6
+ metadata.gz: ee6ac3134f616e98e63f3ad2160325defc99b80e15082c62e8da378e401e3768bb6f75696e96d79f9e48ce1f652b0eeef8767796b8f61d53d717c1eaa405bebc
7
+ data.tar.gz: 766d487ea2ca668819b6dd0c27459843d20be17ec4c1c54f7f114024b68b12c95e63f8aeff9c81b8016efbbd70cc74a32fb513549ad6c10255e1e9d36be4200c
@@ -37,8 +37,8 @@ class Concept
37
37
 
38
38
  @data = {}
39
39
  @data[:tags] = []
40
- @data[:texts] = [] # Used by standard def inputs
41
- @data[:images] = [] # Used by [type => file and type => image_url] def inputs
40
+ @data[:texts] = [] # Used by standard def inputs
41
+ @data[:images] = [] # Used by [type => file and type => image_url] def inputs
42
42
  @data[:tables] = []
43
43
  @data[:neighbors] = []
44
44
  @data[:reference_to] = []
@@ -45,7 +45,7 @@ class ProjectData
45
45
  @param[:logname] = "#{@param[:projectname]}.log"
46
46
  @param[:outputname] = "#{@param[:projectname]}-gift.txt"
47
47
  @param[:lessonname] = "#{@param[:projectname]}.txt"
48
- @param[:yamlname] = "#{@param[:projectname]}-questions.yaml"
48
+ @param[:yamlname] = "#{@param[:projectname]}.yaml"
49
49
  @param[:moodlename] = "#{@param[:projectname]}-moodle.xml"
50
50
 
51
51
  outputdir = get(:outputdir)
@@ -0,0 +1,17 @@
1
+ class FormatCode2Doc
2
+ def call(code)
3
+ out = ""
4
+ title = "#{code.filename} (#{code.type})"
5
+ out << ("-" * title.size + "\n")
6
+ out << "#{title}\n"
7
+ if code.features.size.positive?
8
+ out << "* features: #{code.features.join(", ")}"
9
+ end
10
+ out << "\n"
11
+ code.lines.each_with_index do |line, index|
12
+ out << "#{index} | #{line}\n"
13
+ end
14
+ out << "\n"
15
+ out
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require "terminal-table"
2
+
3
+ class FormatConcept2Doc
4
+ def call(concept)
5
+ out = ""
6
+ title = concept.names.join(", ")
7
+ out << ("-" * title.size + "\n")
8
+ out << "#{title}\n"
9
+ concept.texts.each { |text| out << "* #{text}\n" }
10
+ concept.images.each do |data|
11
+ out << "* (#{data[:type]}) #{data[:url]}\n"
12
+ end
13
+ out << "\n"
14
+ concept.tables.each do |table|
15
+ out << format_table(table)
16
+ end
17
+ out
18
+ end
19
+
20
+ private
21
+
22
+ def format_table(table)
23
+ my_screen_table = Terminal::Table.new do |st|
24
+ st << table.fields
25
+ st << :separator
26
+ table.rows.each { |r| st.add_row r }
27
+ end
28
+ "#{my_screen_table}\n"
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ class FormatProblem2Doc
2
+ def initialize(problem)
3
+ @problem = problem
4
+ end
5
+
6
+ def call
7
+ # attr_accessor :varnames
8
+ # attr_accessor :cases
9
+ out = ""
10
+ title = "Problem: #{@problem.name}"
11
+ out << ("-" * title.size + "\n")
12
+ out << "#{title}\n"
13
+ desc = replace_case_values(@problem.desc)
14
+ out << "#{desc}\n"
15
+ @problem.asks.each_with_index do |ask, index|
16
+ text = replace_case_values(ask[:text])
17
+ out << "#{index + 1}) #{text}\n"
18
+ if ask[:answer]
19
+ answer = replace_case_values(ask[:answer])
20
+ out << " #{answer}\n"
21
+ else
22
+ ask[:steps].each do |step|
23
+ step = replace_case_values(step)
24
+ out << " #{step}\n"
25
+ end
26
+ end
27
+ end
28
+ out << "\n"
29
+ out << "\n"
30
+ out
31
+ end
32
+
33
+ private
34
+
35
+ def replace_case_values(text)
36
+ output = text.clone
37
+ keyvalues = @problem.varnames.zip @problem.cases[0]
38
+ keyvalues.each { |varname, value | output.gsub!(varname, value) }
39
+ output
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "doc/format_code2doc"
2
+ require_relative "doc/format_concept2doc"
3
+ require_relative "doc/format_problem2doc"
4
+ require_relative "../version"
5
+
6
+ class Export2Doc
7
+ def call(data, project)
8
+ file_open(project)
9
+ export_codes(data[:codes])
10
+ export_concepts(data[:concepts])
11
+ export_problems(data[:problems])
12
+ @file.close
13
+ end
14
+
15
+ private
16
+
17
+ def file_open(project)
18
+ @file = File.new(project.get(:lessonpath), "w")
19
+ @file.write("Asker : version #{Asker::VERSION}\n")
20
+ @file.write("Filename : #{project.get(:lessonname)}\n")
21
+ @file.write("Datetime : #{Time.new}\n\n")
22
+ end
23
+
24
+ def export_codes(codes)
25
+ codes.each do |code|
26
+ @file.write(FormatCode2Doc.new.call(code)) if code.process
27
+ end
28
+ end
29
+
30
+ def export_concepts(concepts)
31
+ concepts.each do |concept|
32
+ @file.write(FormatConcept2Doc.new.call(concept)) if concept.process
33
+ end
34
+ end
35
+
36
+ def export_problems(problems)
37
+ problems.each do |problem|
38
+ @file.write(FormatProblem2Doc.new(problem).call) if problem.process
39
+ end
40
+ end
41
+ end
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "concept_ai_gift_exporter"
4
- require_relative "code_gift_exporter"
5
- require_relative "problem_gift_exporter"
3
+ require_relative "gift/export_code2gift"
4
+ require_relative "gift/export_concept2gift"
5
+ require_relative "gift/export_problem2gift"
6
6
  require_relative "../application"
7
7
  require_relative "../version"
8
8
 
9
- module DataGiftExporter
9
+ class Export2Gift
10
10
  ##
11
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
- def self.export_all(data, project)
14
+ def call(data, project)
15
15
  file = File.open(project.get(:outputpath), "w")
16
16
  file.write("// " + ("=" * 50) + "\n")
17
17
  file.write("// #{Asker::NAME} : version #{Asker::VERSION}\n")
@@ -21,9 +21,9 @@ module DataGiftExporter
21
21
  category = Application.instance.config["questions"]["category"]
22
22
  file.write("$CATEGORY: $course$/#{category}\n") unless category.nil?
23
23
 
24
- ConceptAIGiftExporter.export_all(data[:concepts_ai], file)
25
- CodeGiftExporter.export_all(data[:codes_ai], file)
26
- ProblemGiftExporter.new.call(data[:problems], file)
24
+ ExportConcept2Gift.new.call(data[:concepts_ai], file)
25
+ ExportCode2Gift.new.call(data[:codes_ai], file)
26
+ ExportProblem2Gift.new.call(data[:problems], file)
27
27
  file.close
28
28
  end
29
29
  end
@@ -1,9 +1,9 @@
1
1
  require_relative "../application"
2
2
  require_relative "../version"
3
- require_relative "../formatter/question_moodle_formatter"
3
+ require_relative "../formatter/question2moodle_xml"
4
4
 
5
- module DataMoodleExporter
6
- def self.call(data, project)
5
+ class Export2MoodleXML
6
+ def call(data, project)
7
7
  file = File.open(project.get(:moodlepath), "w")
8
8
  add_header(file, project)
9
9
 
@@ -14,7 +14,9 @@ module DataMoodleExporter
14
14
  close(file)
15
15
  end
16
16
 
17
- def self.add_header(file, project)
17
+ private
18
+
19
+ def add_header(file, project)
18
20
  file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
19
21
  file.write("<quiz>\n")
20
22
  file.write("<!--\n#{"=" * 50}\n")
@@ -25,37 +27,37 @@ module DataMoodleExporter
25
27
  file
26
28
  end
27
29
 
28
- def self.close(file)
30
+ def close(file)
29
31
  file.write("</quiz>\n")
30
32
  file.close
31
33
  end
32
34
 
33
- def self.export_concepts(concepts:, file:)
35
+ def export_concepts(concepts:, file:)
34
36
  concepts.each do |concept_ai|
35
37
  next unless concept_ai.concept.process?
36
38
 
37
39
  Application.instance.config["questions"]["stages"].each do |stage|
38
40
  concept_ai.questions[stage].each do |question|
39
- file.write(QuestionMoodleFormatter.to_s(question))
41
+ file.write(Question2MoodleXML.new.format(question))
40
42
  end
41
43
  end
42
44
  end
43
45
  end
44
46
 
45
- def self.export_codes(codes:, file:)
47
+ def export_codes(codes:, file:)
46
48
  codes.each do |code|
47
49
  next unless code.process?
48
50
  code.questions.each do |question|
49
- file.write QuestionMoodleFormatter.to_s(question)
51
+ file.write Question2MoodleXML.new.format(question)
50
52
  end
51
53
  end
52
54
  end
53
55
 
54
- def self.export_problems(problems:, file:)
56
+ def export_problems(problems:, file:)
55
57
  problems.each do |problem|
56
58
  next unless problem.process?
57
59
  problem.questions.each do |question|
58
- file.write QuestionMoodleFormatter.to_s(question)
60
+ file.write Question2MoodleXML.new.format(question)
59
61
  end
60
62
  end
61
63
  end
@@ -0,0 +1,70 @@
1
+ require "yaml"
2
+ require_relative "../formatter/question2hash"
3
+
4
+ class Export2YAML
5
+ ##
6
+ # Export array of ConceptAI objects from Project to YAML output file
7
+ # @param concepts_ai (Array)
8
+ # @param project (Project)
9
+ def call(data, project)
10
+ questions = []
11
+ questions += get_questions_from_codes(data)
12
+ questions += get_questions_from_concepts(data)
13
+ questions += get_questions_from_problems(data)
14
+
15
+ output = {
16
+ lang: project.get(:lang_code),
17
+ projectname: project.get(:projectname),
18
+ questions: questions
19
+ }
20
+
21
+ yamlfile = File.open(project.get(:yamlpath), "w")
22
+ yamlfile.write(output.to_yaml)
23
+ yamlfile.close
24
+ end
25
+
26
+ private
27
+
28
+ def get_questions_from_codes(data)
29
+ questions = []
30
+ data[:codes].each do |code|
31
+ next unless code.process
32
+ code.questions.each do |question|
33
+ questions << Question2Hash.new.format(question)
34
+ end
35
+ end
36
+ questions
37
+ end
38
+
39
+ def get_questions_from_concepts(data)
40
+ questions = []
41
+ data[:concepts_ai].each do |concept_ai|
42
+ questions += get_questions_from_concept concept_ai
43
+ end
44
+ questions
45
+ end
46
+
47
+ def get_questions_from_concept(concept_ai)
48
+ questions = []
49
+ return questions unless concept_ai.concept.process?
50
+
51
+ Application.instance.config["questions"]["stages"].each do |stage|
52
+ concept_ai.questions[stage].each do |question|
53
+ question.lang = concept_ai.concept.lang
54
+ questions << Question2Hash.new.format(question)
55
+ end
56
+ end
57
+ questions
58
+ end
59
+
60
+ def get_questions_from_problems(data)
61
+ questions = []
62
+ data[:problems].each do |problem|
63
+ next unless problem.process
64
+ problem.questions.each do |question|
65
+ questions << Question2Hash.new.format(question)
66
+ end
67
+ end
68
+ questions
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "export2doc"
2
+ require_relative "export2gift"
3
+ require_relative "export2moodle_xml"
4
+ require_relative "export2yaml"
5
+
6
+ ##
7
+ # Export Output data files
8
+ # * YAML, Doc (txt), Gift (ConceptAI, Code) and Moodle XML (ConceptAI, Code)
9
+ class ExportAction
10
+ def call(data, project)
11
+ output = Application.instance.config["output"]
12
+
13
+ Export2Doc.new.call(data, project) if output["doc"] == "yes"
14
+ Export2Gift.new.call(data, project) if output["gift"] == "yes"
15
+ Export2MoodleXML.new.call(data, project) if output["moodle"] == "yes"
16
+ Export2YAML.new.call(data, project) if output["yaml"] == "yes"
17
+ end
18
+ end
@@ -1,17 +1,18 @@
1
- require_relative "../formatter/question_gift_formatter"
1
+ require_relative "question_gift_formatter"
2
2
 
3
- module CodeGiftExporter
3
+ class ExportCode2Gift
4
4
  ##
5
5
  # Export an Array of codes to gift format file
6
6
  # @param codes (Array)
7
- def self.export_all(codes, file)
7
+ def call(codes, file)
8
8
  codes.each { |code| export(code, file) }
9
9
  end
10
10
 
11
+ private
12
+
11
13
  ##
12
14
  # Export 1 code to gift format file
13
- # @param code (Code)
14
- def self.export(code, file)
15
+ def export(code, file)
15
16
  return false unless code.process?
16
17
 
17
18
  file.write head(code)
@@ -21,7 +22,7 @@ module CodeGiftExporter
21
22
  true
22
23
  end
23
24
 
24
- private_class_method def self.head(code)
25
+ def head(code)
25
26
  s = "\n"
26
27
  s += "// " + "=" * 50 + "\n"
27
28
  s += "// Code #{code.type}: #{code.filename} (#{code.questions.size})\n"
@@ -1,22 +1,21 @@
1
- # frozen_string_literal: true
1
+ require_relative "question_gift_formatter"
2
2
 
3
- require_relative "../formatter/question_gift_formatter"
4
-
5
- # Export ConceptIA data to gift to outputfile
6
- module ConceptAIGiftExporter
3
+ class ExportConcept2Gift
7
4
  ##
8
5
  # Export an array of ConceptAI objects from Project into GIFT outpufile
9
6
  # @param concepts_ai (Array)
10
7
  # @param file (File)
11
- def self.export_all(concepts_ai, file)
8
+ def call(concepts_ai, file)
12
9
  concepts_ai.each { |concept_ai| export(concept_ai, file) }
13
10
  end
14
11
 
12
+ private
13
+
15
14
  ##
16
15
  # Export 1 concept_ai from project
17
16
  # @param concept_ai (ConceptAI)
18
17
  # @param file (File)
19
- private_class_method def self.export(concept_ai, file)
18
+ def export(concept_ai, file)
20
19
  return unless concept_ai.concept.process?
21
20
 
22
21
  file.write head(concept_ai.concept.name)
@@ -31,7 +30,7 @@ module ConceptAIGiftExporter
31
30
  # Convert Concept name into gift format head
32
31
  # @param name (String)
33
32
  # @return String
34
- private_class_method def self.head(name)
33
+ def head(name)
35
34
  s = "\n"
36
35
  s += "// " + "=" * 50 + "\n"
37
36
  s += "// Concept name: #{name}\n"
@@ -1,6 +1,6 @@
1
- require_relative "../formatter/question_gift_formatter"
1
+ require_relative "question_gift_formatter"
2
2
 
3
- class ProblemGiftExporter
3
+ class ExportProblem2Gift
4
4
  ##
5
5
  # Export an Array of problems to gift format file
6
6
  # @param problems (Array)
@@ -1,6 +1,3 @@
1
- # frozen_string_literal: false
2
-
3
- # Transform Questions into Gift format
4
1
  module QuestionGiftFormatter
5
2
  ##
6
3
  # Convert question object into gift formatted string
@@ -1,6 +1,7 @@
1
- # Transform Questions into YAML format
2
- module QuestionHashFormatter
3
- def self.to_hash(question)
1
+ require_relative "../logger"
2
+
3
+ class Question2Hash
4
+ def format(question)
4
5
  @question = question
5
6
  # Return question using YAML format
6
7
  s = {}
@@ -9,23 +10,30 @@ module QuestionHashFormatter
9
10
  s[:text] = sanitize(@question.text)
10
11
  s[:type] = @question.type
11
12
  s[:feedback] = sanitize(@question.feedback.to_s)
12
- s[:lang] = @question.lang.code.to_sym
13
13
  case @question.type
14
+ when :boolean
15
+ s[:answer] = @question.good
14
16
  when :choice
15
17
  s[:answer] = sanitize(@question.good)
16
18
  s[:options] = (@question.bads + [@question.good]).shuffle
17
- when :boolean
18
- s[:answer] = @question.good
19
+ when :ddmatch
20
+ s[:answer] = @question.matching
19
21
  when :match
20
22
  s[:answer] = @question.matching
23
+ when :ordering
24
+ s[:answer] = @question.ordering
21
25
  when :short
22
26
  @question.shorts.uniq!
23
27
  s[:answer] = @question.shorts
28
+ else
29
+ Logger.warn "[WARN] Question2Hash: Unkown type (#{@question.type})"
24
30
  end
25
31
  s
26
32
  end
27
33
 
28
- def self.sanitize(input = "")
34
+ private
35
+
36
+ def sanitize(input = "")
29
37
  output = input.dup
30
38
  output.gsub!("#", "\\#")
31
39
  output.tr!("\n", " ")
@@ -1,15 +1,13 @@
1
- # frozen_string_literal: false
2
-
3
1
  require "erb"
4
2
  require_relative "../application"
5
3
 
6
4
  # Transform Questions into Gift format
7
- class QuestionMoodleFormatter
5
+ class Question2MoodleXML
8
6
  ##
9
7
  # Convert question object into gift formatted string
10
8
  # @param question (Question)
11
9
  # @return String
12
- def self.to_s(question)
10
+ def format(question)
13
11
  case question.type
14
12
  when :choice
15
13
  fractions = Application.instance.config["questions"]["fractions"]
@@ -31,7 +29,7 @@ class QuestionMoodleFormatter
31
29
  when :short
32
30
  template = File.read(File.join(File.dirname(__FILE__), "moodle", "shortanswer.erb"))
33
31
  else
34
- warn "[ERROR] QuestionMoodleFormatter: Unknown type (#{question.type})"
32
+ warn "[ERROR] Question2MoodleXML: Unknown type (#{question.type})"
35
33
  exit 1
36
34
  end
37
35
  renderer = ERB.new(template)
@@ -13,7 +13,7 @@ module CodeLoader
13
13
  def self.call(xmldata, filepath)
14
14
  data = read_codedata_from_xml(xmldata, File.basename(filepath))
15
15
  code = Code.new(File.dirname(filepath), data[:path], data[:type])
16
- code.features << data[:features]
16
+ code.features = data[:features]
17
17
  code
18
18
  end
19
19
 
@@ -48,6 +48,7 @@ class ContentLoader
48
48
  lang_code = ProjectData.instance.lang
49
49
  Logger.warn "ContentLoader: Applying default lang (#{lang_code})"
50
50
  end
51
+ ProjectData.instance.set(:lang_code, lang_code)
51
52
  LangFactory.instance.get(lang_code)
52
53
  end
53
54
 
@@ -31,7 +31,12 @@ module EmbeddedFile
31
31
  return load_video_url(value, localdir)
32
32
  end
33
33
 
34
- {text: "<pre>#{File.read(filepath)}</pre>", file: :none, type: :text}
34
+ {
35
+ text: "<pre>#{File.read(filepath)}</pre>",
36
+ file: :none,
37
+ type: :text,
38
+ url: value
39
+ }
35
40
  end
36
41
 
37
42
  def load_audio(value, localdir)
@@ -44,6 +49,7 @@ module EmbeddedFile
44
49
  + Base64.strict_encode64(File.open(filepath, "rb").read) \
45
50
  + "</file>"
46
51
  output[:type] = :audio
52
+ output[:url] = value
47
53
  output
48
54
  end
49
55
 
@@ -51,7 +57,8 @@ module EmbeddedFile
51
57
  {
52
58
  text: "<audio src=\"#{value}\" controls></audio>",
53
59
  file: :none,
54
- type: :url
60
+ type: :url,
61
+ url: value
55
62
  }
56
63
  end
57
64
 
@@ -65,6 +72,7 @@ module EmbeddedFile
65
72
  + Base64.strict_encode64(File.open(filepath, "rb").read) \
66
73
  + "</file>"
67
74
  output[:type] = :image
75
+ output[:url] = value
68
76
  output
69
77
  end
70
78
 
@@ -72,7 +80,8 @@ module EmbeddedFile
72
80
  {
73
81
  text: "<img src=\"#{value}\" alt=\"image\" width=\"400\" height=\"300\">",
74
82
  file: :none,
75
- type: :url
83
+ type: :url,
84
+ url: value
76
85
  }
77
86
  end
78
87
 
@@ -88,6 +97,7 @@ module EmbeddedFile
88
97
  + Base64.strict_encode64(File.open(filepath, "rb").read) \
89
98
  + "</file>"
90
99
  output[:type] = :video
100
+ output[:url] = value
91
101
  output
92
102
  end
93
103
 
@@ -96,7 +106,8 @@ module EmbeddedFile
96
106
  text: "<video controls width=\"400\" height=\"300\">" \
97
107
  + "<source src=\"#{value}\"/></video>",
98
108
  file: :none,
99
- type: :url
109
+ type: :url,
110
+ url: value
100
111
  }
101
112
  end
102
113
  end
data/lib/asker/logger.rb CHANGED
@@ -20,7 +20,7 @@ class Logger
20
20
 
21
21
  def self.warn(msg)
22
22
  msg = Rainbow("[WARN] #{msg}\n").yellow.bright
23
- puts msg if @verbose
23
+ print msg if @verbose
24
24
  @logfile&.write(msg)
25
25
  end
26
26
 
data/lib/asker/start.rb CHANGED
@@ -2,7 +2,7 @@ require_relative "application"
2
2
  require_relative "logger"
3
3
  require_relative "displayer/concept_displayer"
4
4
  require_relative "displayer/stats_displayer"
5
- require_relative "exporter/output_file_exporter"
5
+ require_relative "exporter/export_action"
6
6
  require_relative "loader/project_loader"
7
7
  require_relative "loader/input_loader"
8
8
 
@@ -37,7 +37,7 @@ class Start
37
37
  end
38
38
 
39
39
  def create_output(project, data)
40
- OutputFileExporter.export(data, project)
40
+ ExportAction.new.call(data, project)
41
41
  StatsDisplayer.show(data)
42
42
  Logger.close
43
43
  end
data/lib/asker/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Asker
2
- VERSION = "2.8.0"
2
+ VERSION = "2.9.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.8.0
4
+ version: 2.9.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-07-18 00:00:00.000000000 Z
11
+ date: 2023-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -146,21 +146,24 @@ files:
146
146
  - lib/asker/data/table.rb
147
147
  - lib/asker/data/template.rb
148
148
  - lib/asker/data/world.rb
149
- - lib/asker/deprecated/question_moodlexml_formatter.rb
150
149
  - lib/asker/displayer/code_displayer.rb
151
150
  - lib/asker/displayer/concept_ai_displayer.erb
152
151
  - lib/asker/displayer/concept_ai_displayer.rb
153
152
  - lib/asker/displayer/concept_displayer.rb
154
153
  - lib/asker/displayer/problem_displayer.rb
155
154
  - lib/asker/displayer/stats_displayer.rb
156
- - lib/asker/exporter/code_gift_exporter.rb
157
- - lib/asker/exporter/concept_ai_gift_exporter.rb
158
- - lib/asker/exporter/concept_ai_yaml_exporter.rb
159
- - lib/asker/exporter/concept_doc_exporter.rb
160
- - lib/asker/exporter/data_gift_exporter.rb
161
- - lib/asker/exporter/data_moodle_exporter.rb
162
- - lib/asker/exporter/output_file_exporter.rb
163
- - lib/asker/exporter/problem_gift_exporter.rb
155
+ - lib/asker/exporter/doc/format_code2doc.rb
156
+ - lib/asker/exporter/doc/format_concept2doc.rb
157
+ - lib/asker/exporter/doc/format_problem2doc.rb
158
+ - lib/asker/exporter/export2doc.rb
159
+ - lib/asker/exporter/export2gift.rb
160
+ - lib/asker/exporter/export2moodle_xml.rb
161
+ - lib/asker/exporter/export2yaml.rb
162
+ - lib/asker/exporter/export_action.rb
163
+ - lib/asker/exporter/gift/export_code2gift.rb
164
+ - lib/asker/exporter/gift/export_concept2gift.rb
165
+ - lib/asker/exporter/gift/export_problem2gift.rb
166
+ - lib/asker/exporter/gift/question_gift_formatter.rb
164
167
  - lib/asker/files/asker.ini
165
168
  - lib/asker/files/example-code.haml
166
169
  - lib/asker/files/example-concept.haml
@@ -195,7 +198,6 @@ files:
195
198
  - lib/asker/files/language/sql/mistakes.yaml
196
199
  - lib/asker/files/language/sql/templates.yaml
197
200
  - lib/asker/formatter/code_string_formatter.rb
198
- - lib/asker/formatter/concept_doc_formatter.rb
199
201
  - lib/asker/formatter/concept_string_formatter.rb
200
202
  - lib/asker/formatter/moodle/ddmatch.erb
201
203
  - lib/asker/formatter/moodle/gapfill.erb
@@ -204,9 +206,8 @@ files:
204
206
  - lib/asker/formatter/moodle/ordering.erb
205
207
  - lib/asker/formatter/moodle/shortanswer.erb
206
208
  - lib/asker/formatter/moodle/truefalse.erb
207
- - lib/asker/formatter/question_gift_formatter.rb
208
- - lib/asker/formatter/question_hash_formatter.rb
209
- - lib/asker/formatter/question_moodle_formatter.rb
209
+ - lib/asker/formatter/question2hash.rb
210
+ - lib/asker/formatter/question2moodle_xml.rb
210
211
  - lib/asker/formatter/rb2haml_formatter.rb
211
212
  - lib/asker/lang/lang.rb
212
213
  - lib/asker/lang/lang_factory.rb
@@ -1,69 +0,0 @@
1
- # Transform Questions into Gift format
2
- module QuestionMoodleXMLFormatter
3
- def self.to_s(question)
4
- @question = question
5
-
6
- case @question.type
7
- when :choice
8
- s += choice_to_s(question)
9
- when :boolean
10
- when :match
11
- when :short
12
- end
13
- s.flaten!
14
- end
15
-
16
- def self.choice_to_s(question)
17
- s = []
18
-
19
- penalties = ["", "%-50%", "%-33.33333%", "%-25%", "%-20%"]
20
- penalty = penalties[question.bads.size]
21
-
22
- s << "<!-- question: #{question.name} -->"
23
- s << '<question type="multichoice">'
24
- s << " <name>"
25
- s << " <text>#{question.name}</text>"
26
- s << " </name>"
27
- s << ' <questiontext format="html">'
28
- s << " <text><![CDATA[#{question.text}]]></text>"
29
- s << " </questiontext>"
30
- s << ' <generalfeedback format="html">'
31
- s << " <text>#{question.feedback}</text>"
32
- s << " </generalfeedback>"
33
- s << " <defaultgrade>1.0000000</defaultgrade>"
34
- s << " <penalty>#{penalty}</penalty>"
35
- s << " <hidden>0</hidden>"
36
- s << " <single>true</single>"
37
- s << " <shuffleanswers>#{question.shuffle?}</shuffleanswers>"
38
- s << " <answernumbering>abc</answernumbering>"
39
- s << ' <incorrectfeedback format="html">'
40
- s << " <text>#{question.feedback}</text>"
41
- s << " </incorrectfeedback>"
42
- s << ' <answer fraction="100" format="html">'
43
- s << " <text>#{question.good}</text>"
44
- s << " </answer>"
45
- s << ' <answer fraction="-25" format="html">'
46
- s << " <text>#{question.bad[0]}</text>"
47
- s << " </answer>"
48
- s << " </question>"
49
- s << ' <answer fraction="-25" format="html">'
50
- s << " <text>#{question.bad[1]}</text>"
51
- s << " </answer>"
52
- s << " </question>"
53
- s << ' <answer fraction="-25" format="html">'
54
- s << " <text>#{question.bad[2]}</text>"
55
- s << " </answer>"
56
- s << " </question>"
57
- s
58
- end
59
-
60
- def self.sanitize(input = "")
61
- output = input.dup
62
- output.tr!("\n", " ")
63
- output.tr!(":", ":")
64
- output.tr!("=", "\\=")
65
- # output.gsub!('{', "\\{")
66
- # output.gsub!('}', "\\}")
67
- output
68
- end
69
- end
@@ -1,36 +0,0 @@
1
- require "yaml"
2
- require_relative "../formatter/question_hash_formatter"
3
-
4
- # Use to export data from ConceptIA to YAML format
5
- module ConceptAIYAMLExporter
6
- ##
7
- # Export array of ConceptAI objects from Project to YAML output file
8
- # @param concepts_ai (Array)
9
- # @param project (Project)
10
- def self.export_all(concepts_ai, project)
11
- questions = []
12
- concepts_ai.each do |concept_ai|
13
- questions += get_questions_from concept_ai
14
- end
15
- params = {lang: project.get(:lang),
16
- projectname: project.get(:projectname)}
17
- output = {params: params, questions: questions}
18
-
19
- yamlfile = File.open(project.get(:yamlpath), "w")
20
- yamlfile.write(output.to_yaml)
21
- yamlfile.close
22
- end
23
-
24
- private_class_method def self.get_questions_from(concept_ai)
25
- data = []
26
- return data unless concept_ai.concept.process?
27
-
28
- Application.instance.config["questions"]["stages"].each do |stage|
29
- concept_ai.questions[stage].each do |question|
30
- question.lang = concept_ai.concept.lang
31
- data << QuestionHashFormatter.to_hash(question)
32
- end
33
- end
34
- data
35
- end
36
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../formatter/concept_doc_formatter"
4
- require_relative "../version"
5
-
6
- ##
7
- # Export Concept to Doc file
8
- module ConceptDocExporter
9
- ##
10
- # Export array of concepts to doc
11
- def self.export_all(concepts, project)
12
- file = File.new(project.get(:lessonpath), "w")
13
- file.write("=" * 50 + "\n")
14
- file.write("Created by : #{Asker::NAME} (version #{Asker::VERSION})\n")
15
- file.write("File : #{project.get(:lessonname)}\n")
16
- file.write("Time : #{Time.new}\n")
17
- file.write("=" * 50 + "\n")
18
-
19
- concepts.each do |concept|
20
- file.write(ConceptDocFormatter.to_s(concept)) if concept.process
21
- end
22
- file.close
23
- end
24
- end
@@ -1,18 +0,0 @@
1
- require_relative "concept_ai_yaml_exporter"
2
- require_relative "concept_doc_exporter"
3
- require_relative "data_gift_exporter"
4
- require_relative "data_moodle_exporter"
5
-
6
- ##
7
- # Export Output data files
8
- # * YAML, Doc (txt), Gift (ConceptAI, Code) and Moodle XML (ConceptAI, Code)
9
- module OutputFileExporter
10
- def self.export(data, project)
11
- config = Application.instance.config
12
-
13
- ConceptAIYAMLExporter.export_all(data[:concepts_ai], project) if config["output"]["yaml"] == "yes"
14
- ConceptDocExporter.export_all(data[:concepts], project) if config["output"]["doc"] == "yes"
15
- DataGiftExporter.export_all(data, project) if config["output"]["gift"] == "yes"
16
- DataMoodleExporter.call(data, project) if config["output"]["moodle"] == "yes"
17
- end
18
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: false
2
-
3
- require "rainbow"
4
- require "terminal-table"
5
-
6
- module ConceptDocFormatter
7
- ##
8
- # Formatter Concept into Doc
9
- # @param concept (Concept)
10
- def self.to_s(concept)
11
- out = ""
12
- out << "\n#{Rainbow(concept.name).bg(:blue).bright}\n\n"
13
- concept.texts.each { |i| out << "* #{i}\n" }
14
- out << "\n"
15
- concept.tables.each do |table|
16
- out << table_to_s(table)
17
- end
18
- out
19
- end
20
-
21
- ##
22
- # Formatter Table to Doc
23
- # @param table (Table)
24
- # @return String
25
- def self.table_to_s(table)
26
- my_screen_table = Terminal::Table.new do |st|
27
- st << table.fields
28
- st << :separator
29
- table.rows.each { |r| st.add_row r }
30
- end
31
- "#{my_screen_table}\n"
32
- end
33
- end