asker-tool 2.6.0 → 2.7.0

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