asker-tool 2.6.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/lib/asker/ai/ai.rb +6 -6
- data/lib/asker/ai/ai_calculate.rb +3 -3
- data/lib/asker/ai/code/base_code_ai.rb +5 -30
- data/lib/asker/ai/code/code_ai_factory.rb +6 -12
- data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
- data/lib/asker/ai/code/python_code_ai.rb +35 -36
- data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
- data/lib/asker/ai/code/sql_code_ai.rb +20 -21
- data/lib/asker/ai/concept_ai.rb +12 -22
- data/lib/asker/ai/problem/problem_ai.rb +226 -0
- data/lib/asker/ai/question.rb +34 -45
- data/lib/asker/ai/stages/base_stage.rb +7 -7
- data/lib/asker/ai/stages/stage_b.rb +62 -28
- data/lib/asker/ai/stages/stage_d.rb +10 -10
- data/lib/asker/ai/stages/stage_f.rb +17 -17
- data/lib/asker/ai/stages/stage_i.rb +8 -18
- data/lib/asker/ai/stages/stage_s.rb +28 -26
- data/lib/asker/ai/stages/stage_t.rb +40 -51
- data/lib/asker/application.rb +15 -14
- data/lib/asker/check_input/check_haml_data.rb +52 -51
- data/lib/asker/check_input/check_table.rb +17 -20
- data/lib/asker/check_input.rb +10 -23
- data/lib/asker/cli.rb +43 -24
- data/lib/asker/data/code.rb +10 -9
- data/lib/asker/data/column.rb +21 -17
- data/lib/asker/data/concept.rb +24 -37
- data/lib/asker/data/data_field.rb +2 -2
- data/lib/asker/data/problem.rb +112 -0
- data/lib/asker/data/project_data.rb +11 -15
- data/lib/asker/data/row.rb +25 -23
- data/lib/asker/data/table.rb +25 -46
- data/lib/asker/data/template.rb +7 -7
- data/lib/asker/data/world.rb +3 -3
- data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
- data/lib/asker/displayer/code_displayer.rb +10 -10
- data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
- data/lib/asker/displayer/concept_ai_displayer.rb +17 -17
- data/lib/asker/displayer/concept_displayer.rb +4 -2
- data/lib/asker/displayer/problem_displayer.rb +45 -0
- data/lib/asker/displayer/stats_displayer.rb +7 -12
- data/lib/asker/exporter/code_gift_exporter.rb +2 -2
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
- data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
- data/lib/asker/exporter/data_gift_exporter.rb +14 -15
- data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
- data/lib/asker/exporter/output_file_exporter.rb +9 -8
- data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
- data/lib/asker/files/language/ca/templates.yaml +6 -0
- data/lib/asker/files/language/du/templates.yaml +6 -0
- data/lib/asker/files/language/en/templates.yaml +7 -1
- data/lib/asker/files/language/es/templates.yaml +6 -0
- data/lib/asker/files/language/fr/templates.yaml +6 -0
- data/lib/asker/formatter/code_string_formatter.rb +5 -5
- data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
- data/lib/asker/formatter/concept_string_formatter.rb +6 -6
- data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
- data/lib/asker/formatter/moodle/gapfill.erb +57 -0
- data/lib/asker/formatter/moodle/ordering.erb +41 -0
- data/lib/asker/formatter/question_gift_formatter.rb +41 -14
- data/lib/asker/formatter/question_hash_formatter.rb +5 -6
- data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
- data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
- data/lib/asker/lang/lang.rb +16 -16
- data/lib/asker/lang/lang_factory.rb +13 -16
- data/lib/asker/lang/text_actions.rb +20 -18
- data/lib/asker/loader/code_loader.rb +10 -22
- data/lib/asker/loader/content_loader.rb +42 -49
- data/lib/asker/loader/directory_loader.rb +13 -16
- data/lib/asker/loader/embedded_file.rb +14 -14
- data/lib/asker/loader/file_loader.rb +5 -4
- data/lib/asker/loader/haml_loader.rb +4 -3
- data/lib/asker/loader/image_url_loader.rb +6 -5
- data/lib/asker/loader/input_loader.rb +24 -10
- data/lib/asker/loader/problem_loader.rb +88 -0
- data/lib/asker/loader/project_loader.rb +5 -12
- data/lib/asker/logger.rb +19 -10
- data/lib/asker/skeleton.rb +19 -35
- data/lib/asker/start.rb +44 -0
- data/lib/asker/version.rb +1 -1
- data/lib/asker.rb +7 -52
- metadata +12 -6
- data/lib/asker/ai/code/problem_code_ai.rb +0 -176
- data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
@@ -1,30 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require_relative "concept_ai_gift_exporter"
|
4
|
+
require_relative "code_gift_exporter"
|
5
|
+
require_relative "problem_gift_exporter"
|
6
|
+
require_relative "../application"
|
7
|
+
require_relative "../version"
|
7
8
|
|
8
|
-
# Export Data (ConceptIA and Code) to gift to outputfile
|
9
9
|
module DataGiftExporter
|
10
10
|
##
|
11
|
-
# Export an array of Data (
|
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
14
|
def self.export_all(data, project)
|
15
|
-
file = File.open(project.get(:outputpath),
|
16
|
-
file.write(
|
17
|
-
file.write("//
|
18
|
-
file.write("
|
19
|
-
file.write("//
|
20
|
-
file.write("//
|
21
|
-
|
22
|
-
category = Application.instance.config['questions']['category']
|
15
|
+
file = File.open(project.get(:outputpath), "w")
|
16
|
+
file.write("// " + ("=" * 50) + "\n")
|
17
|
+
file.write("// #{Asker::NAME} : version #{Asker::VERSION}\n")
|
18
|
+
file.write("// Filename : #{project.get(:outputname)}\n")
|
19
|
+
file.write("// Datetime : #{Time.new}\n")
|
20
|
+
file.write("// " + ("=" * 50) + "\n\n")
|
21
|
+
category = Application.instance.config["questions"]["category"]
|
23
22
|
file.write("$CATEGORY: $course$/#{category}\n") unless category.nil?
|
24
23
|
|
25
24
|
ConceptAIGiftExporter.export_all(data[:concepts_ai], file)
|
26
25
|
CodeGiftExporter.export_all(data[:codes_ai], file)
|
27
|
-
|
26
|
+
ProblemGiftExporter.new.call(data[:problems], file)
|
28
27
|
file.close
|
29
28
|
end
|
30
29
|
end
|
@@ -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.
|
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#{
|
14
|
-
file.write("
|
15
|
-
file.write("
|
16
|
-
file.write("
|
17
|
-
file.write("
|
18
|
-
file
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
29
|
-
|
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
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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: '
|
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
|
4
|
-
require
|
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(
|
12
|
-
t.add_row [Rainbow(
|
13
|
-
t.add_row [Rainbow(
|
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
|
4
|
-
require
|
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
|
-
|
22
|
-
|
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(
|
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
|
-
|
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
|
-
|
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 = [
|
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] +
|
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 :
|
35
|
-
s << "
|
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] +
|
41
|
-
j = j[0, 220] +
|
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] +
|
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.
|
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
|