asker-tool 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/lib/asker/ai/ai.rb +6 -6
  4. data/lib/asker/ai/ai_calculate.rb +3 -3
  5. data/lib/asker/ai/code/base_code_ai.rb +5 -30
  6. data/lib/asker/ai/code/code_ai_factory.rb +6 -12
  7. data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
  8. data/lib/asker/ai/code/python_code_ai.rb +35 -36
  9. data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
  10. data/lib/asker/ai/code/sql_code_ai.rb +20 -21
  11. data/lib/asker/ai/concept_ai.rb +12 -22
  12. data/lib/asker/ai/problem/problem_ai.rb +226 -0
  13. data/lib/asker/ai/question.rb +34 -45
  14. data/lib/asker/ai/stages/base_stage.rb +7 -7
  15. data/lib/asker/ai/stages/stage_b.rb +62 -28
  16. data/lib/asker/ai/stages/stage_d.rb +10 -10
  17. data/lib/asker/ai/stages/stage_f.rb +17 -17
  18. data/lib/asker/ai/stages/stage_i.rb +8 -18
  19. data/lib/asker/ai/stages/stage_s.rb +28 -26
  20. data/lib/asker/ai/stages/stage_t.rb +40 -51
  21. data/lib/asker/application.rb +15 -14
  22. data/lib/asker/check_input/check_haml_data.rb +52 -51
  23. data/lib/asker/check_input/check_table.rb +17 -20
  24. data/lib/asker/check_input.rb +10 -23
  25. data/lib/asker/cli.rb +43 -24
  26. data/lib/asker/data/code.rb +10 -9
  27. data/lib/asker/data/column.rb +21 -17
  28. data/lib/asker/data/concept.rb +24 -37
  29. data/lib/asker/data/data_field.rb +2 -2
  30. data/lib/asker/data/problem.rb +112 -0
  31. data/lib/asker/data/project_data.rb +11 -15
  32. data/lib/asker/data/row.rb +25 -23
  33. data/lib/asker/data/table.rb +25 -46
  34. data/lib/asker/data/template.rb +7 -7
  35. data/lib/asker/data/world.rb +3 -3
  36. data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
  37. data/lib/asker/displayer/code_displayer.rb +10 -10
  38. data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
  39. data/lib/asker/displayer/concept_ai_displayer.rb +16 -16
  40. data/lib/asker/displayer/concept_displayer.rb +4 -2
  41. data/lib/asker/displayer/problem_displayer.rb +45 -0
  42. data/lib/asker/displayer/stats_displayer.rb +7 -12
  43. data/lib/asker/exporter/code_gift_exporter.rb +2 -2
  44. data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
  45. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
  46. data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
  47. data/lib/asker/exporter/data_gift_exporter.rb +14 -15
  48. data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
  49. data/lib/asker/exporter/output_file_exporter.rb +9 -8
  50. data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
  51. data/lib/asker/files/language/ca/templates.yaml +6 -0
  52. data/lib/asker/files/language/du/templates.yaml +6 -0
  53. data/lib/asker/files/language/en/templates.yaml +7 -1
  54. data/lib/asker/files/language/es/templates.yaml +6 -0
  55. data/lib/asker/files/language/fr/templates.yaml +6 -0
  56. data/lib/asker/formatter/code_string_formatter.rb +5 -5
  57. data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
  58. data/lib/asker/formatter/concept_string_formatter.rb +6 -6
  59. data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
  60. data/lib/asker/formatter/moodle/gapfill.erb +57 -0
  61. data/lib/asker/formatter/moodle/ordering.erb +41 -0
  62. data/lib/asker/formatter/question_gift_formatter.rb +41 -14
  63. data/lib/asker/formatter/question_hash_formatter.rb +5 -6
  64. data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
  65. data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
  66. data/lib/asker/lang/lang.rb +16 -16
  67. data/lib/asker/lang/lang_factory.rb +13 -16
  68. data/lib/asker/lang/text_actions.rb +20 -18
  69. data/lib/asker/loader/code_loader.rb +10 -22
  70. data/lib/asker/loader/content_loader.rb +42 -49
  71. data/lib/asker/loader/directory_loader.rb +13 -16
  72. data/lib/asker/loader/embedded_file.rb +14 -14
  73. data/lib/asker/loader/file_loader.rb +5 -4
  74. data/lib/asker/loader/haml_loader.rb +4 -3
  75. data/lib/asker/loader/image_url_loader.rb +6 -5
  76. data/lib/asker/loader/input_loader.rb +24 -10
  77. data/lib/asker/loader/problem_loader.rb +88 -0
  78. data/lib/asker/loader/project_loader.rb +5 -12
  79. data/lib/asker/logger.rb +19 -10
  80. data/lib/asker/skeleton.rb +19 -35
  81. data/lib/asker/start.rb +44 -0
  82. data/lib/asker/version.rb +1 -1
  83. data/lib/asker.rb +7 -52
  84. metadata +12 -6
  85. data/lib/asker/ai/code/problem_code_ai.rb +0 -176
  86. data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
  87. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
@@ -1,31 +1,62 @@
1
+ require_relative "../application"
2
+ require_relative "../version"
3
+ require_relative "../formatter/question_moodle_formatter"
1
4
 
2
- require_relative '../version'
3
- require_relative 'concept_ai_moodle_exporter'
4
- require_relative 'code_moodle_exporter'
5
-
6
- # Export data to MoodleXML file
7
5
  module DataMoodleExporter
6
+ def self.call(data, project)
7
+ file = File.open(project.get(:moodlepath), "w")
8
+ add_header(file, project)
9
+
10
+ export_concepts(concepts: data[:concepts_ai], file: file)
11
+ export_codes(codes: data[:codes_ai], file: file)
12
+ export_problems(problems: data[:problems], file: file)
13
+
14
+ close(file)
15
+ end
8
16
 
9
- def self.export_all(data, project)
10
- file = File.open(project.get(:moodlepath), 'w')
17
+ def self.add_header(file, project)
11
18
  file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
12
19
  file.write("<quiz>\n")
13
- file.write("<!--\n#{('=' * 50)}\n")
14
- file.write(" Created by : #{Asker::NAME}")
15
- file.write(" (version #{Asker::VERSION})\n")
16
- file.write(" File : #{project.get(:moodlename)}\n")
17
- file.write(" Time : #{Time.new}\n")
18
- file.write("#{('=' * 50)}\n-->\n\n")
19
-
20
- data[:concepts_ai].each do |concept_ai|
21
- ConceptAIMoodleExporter.run(concept_ai, file)
20
+ file.write("<!--\n#{"=" * 50}\n")
21
+ file.write(" #{Asker::NAME} : version #{Asker::VERSION}\n")
22
+ file.write(" Filename : #{project.get(:moodlename)}\n")
23
+ file.write(" Datetime : #{Time.new}\n")
24
+ file.write("#{"=" * 50}\n-->\n\n")
25
+ file
26
+ end
27
+
28
+ def self.close(file)
29
+ file.write("</quiz>\n")
30
+ file.close
31
+ end
32
+
33
+ def self.export_concepts(concepts:, file:)
34
+ concepts.each do |concept_ai|
35
+ next unless concept_ai.concept.process?
36
+
37
+ Application.instance.config["questions"]["stages"].each do |stage|
38
+ concept_ai.questions[stage].each do |question|
39
+ file.write(QuestionMoodleFormatter.to_s(question))
40
+ end
41
+ end
22
42
  end
43
+ end
23
44
 
24
- data[:codes_ai].each do |code|
25
- CodeMoodleExporter.run(code, file)
45
+ def self.export_codes(codes:, file:)
46
+ codes.each do |code|
47
+ next unless code.process?
48
+ code.questions.each do |question|
49
+ file.write QuestionMoodleFormatter.to_s(question)
50
+ end
26
51
  end
52
+ end
27
53
 
28
- file.write("</quiz>\n")
29
- file.close
54
+ def self.export_problems(problems:, file:)
55
+ problems.each do |problem|
56
+ next unless problem.process?
57
+ problem.questions.each do |question|
58
+ file.write QuestionMoodleFormatter.to_s(question)
59
+ end
60
+ end
30
61
  end
31
62
  end
@@ -1,7 +1,7 @@
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'
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
5
 
6
6
  ##
7
7
  # Export Output data files
@@ -9,9 +9,10 @@ require_relative 'data_moodle_exporter'
9
9
  module OutputFileExporter
10
10
  def self.export(data, project)
11
11
  config = Application.instance.config
12
- ConceptAIYAMLExporter.export_all(data[:concepts_ai], project) if config['output']['yaml'] == 'yes'
13
- ConceptDocExporter.export_all(data[:concepts], project) if config['output']['doc'] == 'yes'
14
- DataGiftExporter.export_all(data, project) if config['output']['gift'] == 'yes'
15
- DataMoodleExporter.export_all(data, project) if config['output']['moodle'] == 'yes'
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"
16
17
  end
17
18
  end
@@ -0,0 +1,30 @@
1
+ require_relative "../formatter/question_gift_formatter"
2
+
3
+ class ProblemGiftExporter
4
+ ##
5
+ # Export an Array of problems to gift format file
6
+ # @param problems (Array)
7
+ def call(problems, file)
8
+ problems.each { |problem| export_one(problem, file) }
9
+ end
10
+
11
+ private
12
+
13
+ def export_one(problem, file)
14
+ return false unless problem.process?
15
+
16
+ file.write head(problem)
17
+ problem.questions.each do |question|
18
+ file.write QuestionGiftFormatter.to_s(question)
19
+ end
20
+ true
21
+ end
22
+
23
+ def head(problem)
24
+ s = "\n"
25
+ s += "// " + "=" * 50 + "\n"
26
+ s += "// Problem: #{problem.name} (#{problem.questions.size} questions)\n"
27
+ s += "// " + "=" * 50 + "\n"
28
+ s
29
+ end
30
+ end
@@ -27,3 +27,9 @@
27
27
  :t8table: 'Concepte <b><%=text1%></b><br/>Completa la següent associació:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: [*]</li></ul>Escriu una paraula.<br/>'
28
28
  :t9table: 'Concepte <b><%=text1%></b><br/>Completa la següent associació:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: <%=text5%></li></ul>Escriu <%=text6%> paraules.<br/>'
29
29
  :code1: '<pre><%=text1%></pre><br/><p>Escriu el número de línia hi ha el primer error. Escriu 0 si no hi ha cap error.</p>'
30
+ :pa1: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Resposta:</b > <%=text3%></p>'
31
+ :pa2: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p>'
32
+ :ps3: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Resposta:</b ></p><pre><%=text3%></pre><br/><i>(Escriure el número de línia on hi ha el primer error. Escriure 0 si no hi ha cap error)</i>'
33
+ :ps4: 'Canvia el pas <%=text1%> pel pas <%=text2%>'
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
+ :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>'
@@ -27,3 +27,9 @@
27
27
  :t8table: 'Begriff <b><%=text1%></b><br/>Vervollständigen Sie / Schreiben Sie einen Begriff:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: [*]</li></ul>Escribir una palabra.<br/>'
28
28
  :t9table: 'Begriff <b><%=text1%></b><br/>Verbinden Sie / Schreiben Sie fogende Begriffe:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: <%=text5%></li></ul>Escribir <%=text6%> palabras.<br/>'
29
29
  :code1: '<pre><%=text1%></pre><br/><p>Nennen Sie die Nummer der Zeile, in der sich der erste Fehler befindet / Wenn es keinen Fehler gibt, setzen Sie 0 ein.</p>'
30
+ :pa1: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><p><b>Antwort:</b > <%=text3%></p>'
31
+ :pa2: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p>'
32
+ :ps3: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><p><b>Antwort:</b ></p><pre><%=text3%></pre><br/><i>(Schreiben Sie die Zeilennummer, in der sich der erste Fehler befindet. Schreiben Sie 0, wenn kein Fehler vorliegt)</i>'
33
+ :ps4: 'Ändere Schritt <%=text1%> in Schritt <%=text2%>'
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
+ :ps6: '<p><%=text1%></p><p><b>Frage:</b> <%=text2%></p><br/><i>(Platzieren Sie jeden Schritt an der richtigen Position innerhalb der Sequenz)</i>'
@@ -1,5 +1,5 @@
1
1
  ---
2
- :none: 'No correct'
2
+ :none: 'None correct'
3
3
  :error: 'Error'
4
4
  :misspelling: 'Misspelling'
5
5
  :true: 'True'
@@ -27,3 +27,9 @@
27
27
  :t8table: '<b>Concept <%=text1%></b><br/>Complete the next association:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: [*]</li></ul>Write only one word.<br/>'
28
28
  :t9table: '<b>Concept <%=text1%></b><br/>Complete the next association:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: <%=text5%></li></ul>Write <%=text6%> words.<br/>'
29
29
  :code1: '<pre><%=text1%></pre><br/><p>Write the number of the first wrong line. Write 0 if there is no fail.</p>'
30
+ :pa1: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><p><b>Answer:</b> <%=text3%></p>'
31
+ :pa2: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p>'
32
+ :ps3: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><p><b>Answer:</b></p><pre><%=text3%></pre><br/><i>(Write the number of the first wrong line. Write 0 if there is no fail)</i>'
33
+ :ps4: 'Change step <%=text1%> by step <%=text2%>'
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
+ :ps6: '<p><%=text1%></p><p><b>Question:</b> <%=text2%></p><br/><i>(Place each step in its correct position within the sequence)</i>'
@@ -27,3 +27,9 @@
27
27
  :t8table: 'Concepto <b><%=text1%></b><br/>Completa la siguiente asociación:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: [*]</li></ul>Escribir una palabra.<br/>'
28
28
  :t9table: 'Concepto <b><%=text1%></b><br/>Completa la siguiente asociación:<br/><ul><li><%=text2%>: "<%=text3%>"</li><li><%=text4%>: <%=text5%></li></ul>Escribir <%=text6%> palabras.<br/>'
29
29
  :code1: '<pre><%=text1%></pre><br/><p>Escribir el número de línea donde está el primer error. Escribir 0 si no hay ningún error.</p>'
30
+ :pa1: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Respuesta:</b> <%=text3%></p>'
31
+ :pa2: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p>'
32
+ :ps3: '<p><%=text1%></p><p><b>Pregunta:</b> <%=text2%></p><p><b>Respuesta:</b></p><pre><%=text3%></pre><br/><i>(Escribir el número de línea donde está el primer error. Escribir 0 si no hay ningún error)</i>'
33
+ :ps4: 'Cambia el paso <%=text1%> por el paso <%=text2%>'
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
+ :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>'
@@ -27,3 +27,9 @@
27
27
  :t8table: "Concept <b><%=text1%></b><br/>Complétez l'association suivante:<br/><ul><li><%=text2%>: \"<%=text3%>\"</li><li><%=text4%>: [*]</li></ul>Écrire un mot.<br/>"
28
28
  :t9table: "Concept <b><%=text1%></b><br/>Complétez l'association suivante:<br/><ul><li><%=text2%>: \"<%=text3%>\"</li><li><%=text4%>: <%=text5%></li></ul>Écrire<%=text6%> mots.<br/>"
29
29
  :code1: "<pre><%=text1%></pre><br/><p>Écrire le numéro de ligne où se trouve la première erreur. Écrire 0 s'il n'y a aucune erreur.</p>"
30
+ :pa1 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><p><b>Réponse :</b > <%=text3%></p>"
31
+ :pa2 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p>"
32
+ :ps3 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><p><b>Réponse :</b ></p><pre><%=text3%></pre><br/><i>(Écrivez le numéro de ligne où se trouve la première erreur. Écrivez 0 s'il n'y a pas d'erreur)</i>"
33
+ :ps4: "Changer l'étape <%=text1%> en étape <%=text2%>"
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
+ :ps6 : "<p><%=text1%></p><p><b>Question :</b> <%=text2%></p><br/><i>(Placez chaque étape dans sa position correcte dans la séquence)</i>"
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rainbow'
4
- require 'terminal-table'
3
+ require "rainbow"
4
+ require "terminal-table"
5
5
 
6
6
  # Define methods to trasnforme Code object into String
7
7
  module CodeStringFormatter
8
8
  def self.to_s(code)
9
9
  t = Terminal::Table.new
10
10
  msg = Rainbow(code.filename).white.bg(:blue).bright
11
- t.add_row [Rainbow('Code').bright, msg]
12
- t.add_row [Rainbow('Type').blue, code.type.to_s]
13
- t.add_row [Rainbow('Lines').blue, code.lines_to_s(code.lines)]
11
+ t.add_row [Rainbow("Code").bright, msg]
12
+ t.add_row [Rainbow("Type").blue, code.type.to_s]
13
+ t.add_row [Rainbow("Lines").blue, code.lines_to_s(code.lines)]
14
14
  "#{t}\n"
15
15
  end
16
16
  end
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'rainbow'
4
- require 'terminal-table'
3
+ require "rainbow"
4
+ require "terminal-table"
5
5
 
6
6
  module ConceptDocFormatter
7
7
  ##
8
8
  # Formatter Concept into Doc
9
9
  # @param concept (Concept)
10
10
  def self.to_s(concept)
11
- out = ''
11
+ out = ""
12
12
  out << "\n#{Rainbow(concept.name).bg(:blue).bright}\n\n"
13
13
  concept.texts.each { |i| out << "* #{i}\n" }
14
14
  out << "\n"
@@ -18,18 +18,18 @@ module ConceptStringFormatter
18
18
  private_class_method def self.get_tt_rows(concept)
19
19
  rows = []
20
20
  rows << [Rainbow(concept.id.to_s).bright,
21
- Rainbow(concept.name(:screen)).green.bright]
22
- # + " (lang=#{concept.lang.lang}) "]
21
+ Rainbow(concept.name(:screen)).green.bright]
22
+ # + " (lang=#{concept.lang.lang}) "]
23
23
  # rows << [Rainbow("Filename").white, concept.filename]
24
24
  # rows << [Rainbow("Context").white, concept.context.join(', ').to_s]
25
- rows << [Rainbow("Tags").white, concept.tags.join(', ').to_s]
25
+ rows << [Rainbow("Tags").white, concept.tags.join(", ").to_s]
26
26
  unless concept.reference_to.size.zero?
27
27
  rows << [Rainbow("Reference to").white,
28
- concept.reference_to.join(', ')[0...70].to_s]
28
+ concept.reference_to.join(", ")[0...70].to_s]
29
29
  end
30
30
  unless concept.referenced_by.size.zero?
31
31
  rows << [Rainbow("Referenced by").white,
32
- concept.referenced_by.join(', ')[0...70].to_s]
32
+ concept.referenced_by.join(", ")[0...70].to_s]
33
33
  end
34
34
  rows << format_texts(concept)
35
35
  unless concept.images.size.zero?
@@ -50,7 +50,7 @@ module ConceptStringFormatter
50
50
  list << i.to_s
51
51
  next
52
52
  end
53
- list << i[0...70].to_s + '...'
53
+ list << i[0...70].to_s + "..."
54
54
  end
55
55
  # [Rainbow("def").white, list.join("\n")]
56
56
  [Rainbow("def").white, list.size.to_s]
@@ -0,0 +1,40 @@
1
+ <% unless question.comment.nil? || question.comment.empty? %>
2
+ <!-- question: <%= question.comment %> -->
3
+ <% end %>
4
+ <question type="ddmatch">
5
+ <name>
6
+ <text><%= question.name %></text>
7
+ </name>
8
+ <questiontext format="html">
9
+ <text><![CDATA[<%= question.text %>]]></text>
10
+ <% unless question.encode == :none %>
11
+ <%= question.encode %>
12
+ <% end %>
13
+ </questiontext>
14
+ <generalfeedback format="html">
15
+ <text></text>
16
+ </generalfeedback>
17
+ <defaultgrade>1.0000000</defaultgrade>
18
+ <penalty>0.3333333</penalty>
19
+ <hidden>0</hidden>
20
+ <idnumber></idnumber>
21
+ <shuffleanswers>true</shuffleanswers>
22
+ <correctfeedback format="html">
23
+ <text></text>
24
+ </correctfeedback>
25
+ <partiallycorrectfeedback format="html">
26
+ <text></text>
27
+ </partiallycorrectfeedback>
28
+ <incorrectfeedback format="html">
29
+ <text></text>
30
+ </incorrectfeedback>
31
+ <shownumcorrect/>
32
+ <% question.matching.each do |i, j| %>
33
+ <subquestion format="html">
34
+ <text><![CDATA[<%= i %>]]></text>
35
+ <answer format="html">
36
+ <text><![CDATA[<%= j %>]]></text>
37
+ </answer>
38
+ </subquestion>
39
+ <% end %>
40
+ </question>
@@ -0,0 +1,57 @@
1
+ <% unless question.comment.nil? || question.comment.empty? %>
2
+ <!-- question: <%= question.comment %> -->
3
+ <% end %>
4
+ <question type="gapfill">
5
+ <name>
6
+ <text><%= question.name %></text>
7
+ </name>
8
+ <questiontext format="html">
9
+ <text><![CDATA[<%= question.text %>]]></text>
10
+ <% unless question.encode == :none %>
11
+ <%= question.encode %>
12
+ <% end %>
13
+ </questiontext>
14
+ <generalfeedback format="html">
15
+ <text></text>
16
+ </generalfeedback>
17
+ <defaultgrade>2.0000000</defaultgrade>
18
+ <penalty>0.3333333</penalty>
19
+ <hidden>0</hidden>
20
+ <idnumber></idnumber>
21
+ <answerdisplay>dragdrop</answerdisplay>
22
+ <delimitchars>[]</delimitchars>
23
+ <casesensitive>0</casesensitive>
24
+ <noduplicates>0</noduplicates>
25
+ <disableregex>0</disableregex>
26
+ <fixedgapsize>0</fixedgapsize>
27
+ <optionsaftertext>0</optionsaftertext>
28
+ <letterhints>0</letterhints>
29
+ <singleuse>0</singleuse>
30
+ <% question.shorts.uniq! %>
31
+ <% question.shorts.each do |i| %>
32
+ <answer fraction="100" format="moodle_auto_format">
33
+ <text><![CDATA[<%= i %>]]></text>
34
+ <feedback format="html">
35
+ <text></text>
36
+ </feedback>
37
+ </answer>
38
+ <% end %>
39
+ <delimitchars>[]</delimitchars>
40
+ <answerdisplay>dragdrop</answerdisplay>
41
+ <casesensitive>0</casesensitive>
42
+ <noduplicates>0</noduplicates>
43
+ <disableregex>0</disableregex>
44
+ <fixedgapsize>0</fixedgapsize>
45
+ <optionsaftertext>0</optionsaftertext>
46
+ <letterhints>0</letterhints>
47
+ <!-- Gapfill release:2.133 version:2022032500 Moodle version:2020061514.02 release:3.9.14+ (Build: 20220603) -->
48
+ <correctfeedback format="html">
49
+ <text></text>
50
+ </correctfeedback>
51
+ <partiallycorrectfeedback format="html">
52
+ <text></text>
53
+ </partiallycorrectfeedback>
54
+ <incorrectfeedback format="html">
55
+ <text></text>
56
+ </incorrectfeedback>
57
+ </question>
@@ -0,0 +1,41 @@
1
+ <% unless question.comment.nil? || question.comment.empty? %>
2
+ <!-- question: <%= question.comment %> -->
3
+ <% end %>
4
+ <question type="ordering">
5
+ <name>
6
+ <text><%= question.name %></text>
7
+ </name>
8
+ <questiontext format="html">
9
+ <text><![CDATA[<%= question.text %>]]></text>
10
+ <% unless question.encode == :none %>
11
+ <%= question.encode %>
12
+ <% end %>
13
+ </questiontext>
14
+ <generalfeedback format="html">
15
+ <text><![CDATA[<%= question.feedback.to_s %>]]></text>
16
+ </generalfeedback>
17
+ <defaultgrade>1.0000000</defaultgrade>
18
+ <penalty>0.3333333</penalty>
19
+ <hidden>0</hidden>
20
+ <idnumber></idnumber>
21
+ <layouttype>VERTICAL</layouttype>
22
+ <selecttype>ALL</selecttype>
23
+ <selectcount>0</selectcount>
24
+ <gradingtype>ABSOLUTE_POSITION</gradingtype>
25
+ <showgrading>SHOW</showgrading>
26
+ <numberingstyle>none</numberingstyle>
27
+ <correctfeedback format="html">
28
+ <text>Respuesta correcta</text>
29
+ </correctfeedback>
30
+ <partiallycorrectfeedback format="html">
31
+ <text>Respuesta parcialmente correcta.</text>
32
+ </partiallycorrectfeedback>
33
+ <incorrectfeedback format="html">
34
+ <text>Respuesta incorrecta.</text>
35
+ </incorrectfeedback>
36
+ <% question.ordering.each_with_index do |step, index| %>
37
+ <answer fraction="<%= index + 1 %>" format="moodle_auto_format">
38
+ <text><%= step %></text>
39
+ </answer>
40
+ <% end %>
41
+ </question>
@@ -7,7 +7,7 @@ module QuestionGiftFormatter
7
7
  # @param question (Question)
8
8
  # @return String
9
9
  def self.to_s(question)
10
- s = ''
10
+ s = ""
11
11
  return s unless question.encode == :none
12
12
 
13
13
  # Return question using gift format
@@ -16,40 +16,48 @@ module QuestionGiftFormatter
16
16
  s << "::#{question.name}::[html]#{sanitize(question.text)}\n"
17
17
 
18
18
  case question.type
19
+ when :boolean
20
+ s << "{#{question.good}#####{sanitize(question.feedback.to_s)}}\n\n"
19
21
  when :choice
20
22
  s += "{\n"
21
23
  a = [" =#{sanitize(question.good)}\n"]
22
- penalties = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
24
+ penalties = ["", "%-50%", "%-33.33333%", "%-25%", "%-20%"]
23
25
  penalty = penalties[question.bads.size]
24
26
 
25
27
  question.bads.each { |i| a << (" ~#{penalty}" + sanitize(i) + "\n") }
26
28
  a.shuffle! if question.shuffle?
27
29
  a.each do |i|
28
30
  text = i
29
- text = i[0, 220] + '...(ERROR: text too long)' if text.size > 255
31
+ text = i[0, 220] + "...(ERROR: text too long)" if text.size > 255
30
32
  s << text
31
33
  end
32
34
  s += " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
33
35
  s += "}\n\n"
34
- when :boolean
35
- s << "{#{question.good}#####{sanitize(question.feedback.to_s)}}\n\n"
36
+ when :ddmatch
37
+ s << "// WARNING: can't export ddmatch questions to this format"
38
+ when :gapfill
39
+ s << "// WARNING: can't export gapfill questions to this format"
36
40
  when :match
37
41
  s << "{\n"
38
42
  a = []
39
43
  question.matching.each do |i, j|
40
- i = i[0, 220] + '...(ERROR: text too long)' if i.size > 255
41
- j = j[0, 220] + '...(ERROR: text too long)' if j.size > 255
44
+ i = i[0, 220] + "...(ERROR: text too long)" if i.size > 255
45
+ j = j[0, 220] + "...(ERROR: text too long)" if j.size > 255
42
46
  a << " =#{sanitize(i)} -> #{sanitize(j)}\n"
43
47
  end
44
48
  a.shuffle! if question.shuffle?
45
49
  a.each { |i| s << i }
46
50
  s << "}\n\n"
51
+ when :ordering
52
+ s << "{>0 ALL VERTICAL ABSOLUTE_POSITION SHOW none\n"
53
+ question.ordering.each { |i| s << "#{i}\n" }
54
+ s << "}\n\n"
47
55
  when :short
48
56
  s << "{\n"
49
57
  question.shorts.uniq!
50
58
  question.shorts.each do |i|
51
59
  text = i
52
- text = i[0, 220] + '...(ERROR: too long)' if text.size > 255
60
+ text = i[0, 220] + "...(ERROR: too long)" if text.size > 255
53
61
  s << " =%100%#{text}#\n"
54
62
  end
55
63
  s << " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
@@ -62,14 +70,33 @@ module QuestionGiftFormatter
62
70
  # Sanitize gift text
63
71
  # @param input (String)
64
72
  # @return String
65
- def self.sanitize(input = '')
73
+ def self.sanitize(input = "")
74
+ return sanitize_exclude_pre(input) if input.include? '<pre>'
75
+
66
76
  output = input.dup
67
- output.gsub!('#', '\#')
77
+ output.gsub!("#", '\#')
68
78
  output.gsub!("\n", " ")
69
- output.gsub!(':', '\:')
70
- output.gsub!('=', '\=')
71
- output.gsub!("\{", "\\{")
72
- output.gsub!("\}", "\\}")
79
+ output.gsub!(":", '\:')
80
+ output.gsub!("=", '\=')
81
+ output.gsub!("{", "\\{")
82
+ output.gsub!("}", "\\}")
83
+
73
84
  output
74
85
  end
86
+
87
+ def self.sanitize_exclude_pre(input = "")
88
+ pres = input.split('<pre>')
89
+
90
+ pres = [pres[0]] + pres[1].split("</pre>")
91
+ [0, 2].each do |index|
92
+ pres[index].gsub!("#", '\#')
93
+ pres[index].gsub!("\n", " ")
94
+ pres[index].gsub!(":", '\:')
95
+ pres[index].gsub!("=", '\=')
96
+ pres[index].gsub!("{", "\\{")
97
+ pres[index].gsub!("}", "\\}")
98
+ end
99
+
100
+ pres.join("")
101
+ end
75
102
  end
@@ -1,4 +1,3 @@
1
-
2
1
  # Transform Questions into YAML format
3
2
  module QuestionHashFormatter
4
3
  def self.to_hash(question)
@@ -26,14 +25,14 @@ module QuestionHashFormatter
26
25
  s
27
26
  end
28
27
 
29
- def self.sanitize(input = '')
28
+ def self.sanitize(input = "")
30
29
  output = input.dup
31
30
  output.gsub!("#", "\\#")
32
- output.gsub!("\n", " ")
33
- #output.gsub!(":", "\\:")
31
+ output.tr!("\n", " ")
32
+ # output.gsub!(":", "\\:")
34
33
  output.gsub!("=", "\\=")
35
- output.gsub!("\{", "\\{")
36
- output.gsub!("\}", "\\}")
34
+ output.gsub!("{", "\\{")
35
+ output.gsub!("}", "\\}")
37
36
  output
38
37
  end
39
38
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'erb'
4
- require_relative '../application'
3
+ require "erb"
4
+ require_relative "../application"
5
5
 
6
6
  # Transform Questions into Gift format
7
7
  class QuestionMoodleFormatter
@@ -12,20 +12,27 @@ class QuestionMoodleFormatter
12
12
  def self.to_s(question)
13
13
  case question.type
14
14
  when :choice
15
- fractions = Application.instance.config['questions']['fractions']
15
+ fractions = Application.instance.config["questions"]["fractions"]
16
16
  penalties = fractions
17
17
  # penalties = ['', '-50', '-33.33333', '-25', '-20']
18
18
  # puts "[DEBUG] fractions : #{fractions}"
19
19
  # puts "[DEBUG] penalties : #{penalties}"
20
20
 
21
21
  penalty = penalties[question.bads.size]
22
- template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'multichoice.erb'))
22
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "multichoice.erb"))
23
23
  when :boolean
24
- template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'truefalse.erb'))
24
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "truefalse.erb"))
25
+ when :ddmatch
26
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "ddmatch.erb"))
25
27
  when :match
26
- template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'matching.erb'))
28
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "matching.erb"))
29
+ when :ordering
30
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "ordering.erb"))
27
31
  when :short
28
- template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'shortanswer.erb'))
32
+ template = File.read(File.join(File.dirname(__FILE__), "moodle", "shortanswer.erb"))
33
+ else
34
+ warn "[ERROR] QuestionMoodleFormatter: Unkown type (#{question.type})"
35
+ exit 1
29
36
  end
30
37
  renderer = ERB.new(template)
31
38
  renderer.result(binding)
@@ -1,5 +1,7 @@
1
1
  # UNDER DEVELOPMENT!!
2
2
 
3
+ require_relative "../logger"
4
+
3
5
  module Rb2HamlExporter
4
6
  def self.export(filename)
5
7
  check_file filename
@@ -8,19 +10,18 @@ module Rb2HamlExporter
8
10
  end
9
11
 
10
12
  def self.check_file(filename)
11
- unless File.extname(filename).casecmp('.rb').zero?
12
- msg = "[ERROR] Rb2HamlExporter: File name error #{filename}"
13
- raise msg
13
+ unless File.extname(filename).casecmp(".rb").zero?
14
+ Logger.error "Rb2HamlExporter: File name error #{filename}"
15
+ exit 1
14
16
  end
15
17
  unless File.exist? filename
16
- msg = "[ERROR] Rb2HamlExporter: File #{filename} not found!"
17
- raise msg
18
+ Logger.error "Rb2HamlExporter: File #{filename} not found!"
19
+ exit 1
18
20
  end
19
21
  end
20
22
 
21
23
  class Map
22
24
  end
23
-
24
25
  end
25
26
 
26
- Rb2HamlExporter.export('docs/examples/home/rb/furniture.rb')
27
+ Rb2HamlExporter.export("docs/examples/home/rb/furniture.rb")