asker-tool 2.8.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
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