asker-tool 2.5.9 → 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.
- checksums.yaml +4 -4
- data/README.md +10 -7
- data/lib/asker/ai/ai.rb +17 -22
- data/lib/asker/ai/ai_calculate.rb +10 -17
- 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/main.rb +6 -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 +54 -76
- data/lib/asker/application.rb +15 -14
- data/lib/asker/check_input/check_haml_data.rb +57 -51
- data/lib/asker/check_input/check_table.rb +26 -19
- data/lib/asker/check_input.rb +10 -22
- 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 +22 -34
- data/lib/asker/displayer/concept_displayer.rb +9 -11
- 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 +27 -24
- 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 +29 -24
- data/lib/asker/loader/file_loader.rb +7 -6
- data/lib/asker/loader/haml_loader.rb +6 -5
- data/lib/asker/loader/image_url_loader.rb +21 -18
- data/lib/asker/loader/input_loader.rb +27 -14
- data/lib/asker/loader/problem_loader.rb +88 -0
- data/lib/asker/loader/project_loader.rb +11 -28
- data/lib/asker/logger.rb +22 -13
- data/lib/asker/skeleton.rb +27 -43
- data/lib/asker/start.rb +44 -0
- data/lib/asker/version.rb +1 -1
- data/lib/asker.rb +7 -53
- metadata +12 -20
- 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,7 +1,7 @@
|
|
|
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 transform Concept into String
|
|
7
7
|
module ConceptStringFormatter
|
|
@@ -15,32 +15,33 @@ module ConceptStringFormatter
|
|
|
15
15
|
tt.to_s
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
# rubocop:disable Metrics/AbcSize
|
|
19
|
-
# rubocop:disable Metrics/MethodLength
|
|
20
18
|
private_class_method def self.get_tt_rows(concept)
|
|
21
19
|
rows = []
|
|
22
20
|
rows << [Rainbow(concept.id.to_s).bright,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
rows << [Rainbow(
|
|
26
|
-
rows << [Rainbow(
|
|
27
|
-
rows << [Rainbow(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
Rainbow(concept.name(:screen)).green.bright]
|
|
22
|
+
# + " (lang=#{concept.lang.lang}) "]
|
|
23
|
+
# rows << [Rainbow("Filename").white, concept.filename]
|
|
24
|
+
# rows << [Rainbow("Context").white, concept.context.join(', ').to_s]
|
|
25
|
+
rows << [Rainbow("Tags").white, concept.tags.join(", ").to_s]
|
|
26
|
+
unless concept.reference_to.size.zero?
|
|
27
|
+
rows << [Rainbow("Reference to").white,
|
|
28
|
+
concept.reference_to.join(", ")[0...70].to_s]
|
|
29
|
+
end
|
|
30
|
+
unless concept.referenced_by.size.zero?
|
|
31
|
+
rows << [Rainbow("Referenced by").white,
|
|
32
|
+
concept.referenced_by.join(", ")[0...70].to_s]
|
|
33
|
+
end
|
|
32
34
|
rows << format_texts(concept)
|
|
33
35
|
unless concept.images.size.zero?
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
counter = concept.images.size
|
|
37
|
+
# counter1 = 0
|
|
38
|
+
# concept.images.each { |image| counter1 += 1 if image[:file] == :none }
|
|
39
|
+
# counter2 = concept.images.size - counter1
|
|
40
|
+
rows << [Rainbow("def(file)").white, "#{counter} file/s"]
|
|
38
41
|
end
|
|
39
42
|
rows << format_tables(concept) unless concept.tables.count.zero?
|
|
40
43
|
rows << format_neighbors(concept)
|
|
41
44
|
end
|
|
42
|
-
# rubocop:enable Metrics/AbcSize
|
|
43
|
-
# rubocop:enable Metrics/MethodLength
|
|
44
45
|
|
|
45
46
|
private_class_method def self.format_texts(concept)
|
|
46
47
|
list = []
|
|
@@ -49,22 +50,24 @@ module ConceptStringFormatter
|
|
|
49
50
|
list << i.to_s
|
|
50
51
|
next
|
|
51
52
|
end
|
|
52
|
-
list << i[0...70].to_s +
|
|
53
|
+
list << i[0...70].to_s + "..."
|
|
53
54
|
end
|
|
54
|
-
[Rainbow(
|
|
55
|
+
# [Rainbow("def").white, list.join("\n")]
|
|
56
|
+
[Rainbow("def").white, list.size.to_s]
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
private_class_method def self.format_tables(concept)
|
|
58
60
|
return [] if concept.tables.count.zero?
|
|
59
61
|
|
|
60
62
|
list = concept.tables.map(&:to_s)
|
|
61
|
-
[Rainbow(
|
|
63
|
+
[Rainbow("tables").white, list.join("\n")]
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
private_class_method def self.format_neighbors(concept)
|
|
65
67
|
list = concept.neighbors[0..4].map do |i|
|
|
66
|
-
|
|
68
|
+
value = Rainbow(i[:value].to_s[0..4]).white
|
|
69
|
+
"#{value} #{i[:concept].name(:screen)}"
|
|
67
70
|
end
|
|
68
|
-
[Rainbow(
|
|
71
|
+
[Rainbow("neighbors").white, list.join("\n")]
|
|
69
72
|
end
|
|
70
73
|
end
|
|
@@ -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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: false
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require_relative
|
|
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[
|
|
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__),
|
|
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__),
|
|
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__),
|
|
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__),
|
|
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(
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
17
|
-
|
|
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(
|
|
27
|
+
Rb2HamlExporter.export("docs/examples/home/rb/furniture.rb")
|
data/lib/asker/lang/lang.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
require
|
|
3
|
-
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative '../logger'
|
|
1
|
+
require "erb"
|
|
2
|
+
require "yaml"
|
|
3
|
+
require_relative "text_actions"
|
|
4
|
+
require_relative "../logger"
|
|
6
5
|
|
|
7
6
|
class Lang
|
|
8
7
|
include TextActions
|
|
9
8
|
|
|
10
|
-
attr_reader :code
|
|
9
|
+
attr_reader :code
|
|
10
|
+
attr_reader :mistakes
|
|
11
11
|
|
|
12
|
-
def initialize(code =
|
|
12
|
+
def initialize(code = "en")
|
|
13
13
|
@code = code.to_s
|
|
14
14
|
load_files
|
|
15
15
|
end
|
|
@@ -21,23 +21,23 @@ class Lang
|
|
|
21
21
|
private
|
|
22
22
|
|
|
23
23
|
def load_files
|
|
24
|
-
dirbase = File.join(File.dirname(__FILE__),
|
|
25
|
-
filepath = File.join(dirbase, @code,
|
|
24
|
+
dirbase = File.join(File.dirname(__FILE__), "..", "files", "language")
|
|
25
|
+
filepath = File.join(dirbase, @code, "templates.yaml")
|
|
26
26
|
@templates = load_yaml_file(filepath)
|
|
27
|
-
filepath = File.join(dirbase, @code,
|
|
27
|
+
filepath = File.join(dirbase, @code, "connectors.yaml")
|
|
28
28
|
@connectors = load_yaml_file(filepath)
|
|
29
|
-
filepath = File.join(dirbase, @code,
|
|
29
|
+
filepath = File.join(dirbase, @code, "mistakes.yaml")
|
|
30
30
|
@mistakes = load_yaml_file(filepath)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def load_yaml_file(filepath)
|
|
34
34
|
begin
|
|
35
35
|
content = YAML.load(File.new(filepath))
|
|
36
|
-
rescue
|
|
37
|
-
Logger.
|
|
38
|
-
|
|
39
|
-
Logger.
|
|
40
|
-
|
|
36
|
+
rescue => e
|
|
37
|
+
Logger.error "Lang: YAML loading error (#{filepath})"
|
|
38
|
+
Logger.error " : Revise apostrophe into string without \\ symbol"
|
|
39
|
+
Logger.error " : #{e}"
|
|
40
|
+
exit 1
|
|
41
41
|
end
|
|
42
42
|
content
|
|
43
43
|
end
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
3
|
+
require "singleton"
|
|
4
|
+
require_relative "lang"
|
|
5
|
+
require_relative "../application"
|
|
6
|
+
require_relative "../logger"
|
|
6
7
|
|
|
7
8
|
##
|
|
8
|
-
# LangFactory singleton class.
|
|
9
9
|
# * Read all language codes defined into configuration file
|
|
10
10
|
# * and load every language
|
|
11
11
|
# Lang objects are reused
|
|
12
12
|
class LangFactory
|
|
13
13
|
include Singleton
|
|
14
14
|
|
|
15
|
-
##
|
|
16
|
-
# Read all language codes from configuration file and load every language
|
|
17
15
|
def initialize
|
|
18
|
-
|
|
16
|
+
# Read all language codes from configuration file and load every language
|
|
17
|
+
@default = Application.instance.config["languages"]["default"].downcase
|
|
19
18
|
@langs = {}
|
|
20
|
-
Application.instance.config[
|
|
19
|
+
Application.instance.config["languages"].each_pair do |key, value|
|
|
21
20
|
code = key.downcase
|
|
22
|
-
next if code ==
|
|
21
|
+
next if code == "default"
|
|
23
22
|
|
|
24
|
-
@langs[code] = Lang.new(code) if value.downcase ==
|
|
23
|
+
@langs[code] = Lang.new(code) if value.downcase == "yes"
|
|
25
24
|
end
|
|
26
25
|
end
|
|
27
26
|
|
|
@@ -31,15 +30,13 @@ class LangFactory
|
|
|
31
30
|
def get(code)
|
|
32
31
|
return @langs[code] unless @langs[code].nil?
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
Logger.error "LangFactory: Unkown Lang code: #{code}"
|
|
34
|
+
Logger.error " (a) Change input file code lang"
|
|
35
|
+
Logger.error " (b) Revise configuration from asker.ini"
|
|
36
|
+
Logger.error " (c) Revise template files"
|
|
38
37
|
exit 1
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
##
|
|
42
|
-
# Return default Lang object
|
|
43
40
|
def default
|
|
44
41
|
get(@default)
|
|
45
42
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
require_relative "../logger"
|
|
4
|
+
|
|
5
5
|
module TextActions
|
|
6
6
|
##
|
|
7
|
+
# Set of functions used by Lang class
|
|
7
8
|
# Return text indicated by lang code...
|
|
8
9
|
def text_for(option, *input)
|
|
9
10
|
@_text1 = input[0] # FIXME: done to avoid linter complaints.
|
|
@@ -14,9 +15,10 @@ module TextActions
|
|
|
14
15
|
@_text6 = input[5]
|
|
15
16
|
@_text7 = input[6]
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
if @templates[option].nil?
|
|
19
|
+
Logger.error "TextActions: Unkown template (#{option})"
|
|
20
|
+
exit 1
|
|
21
|
+
end
|
|
20
22
|
renderer = ERB.new(@templates[option])
|
|
21
23
|
renderer.result(binding)
|
|
22
24
|
end
|
|
@@ -55,12 +57,12 @@ module TextActions
|
|
|
55
57
|
# @param filter (Boolean) true => apply filter, false => dont filter
|
|
56
58
|
# @return Array
|
|
57
59
|
def text_filter_connectors(input, filter)
|
|
58
|
-
input_lines = input.split(
|
|
60
|
+
input_lines = input.split(".")
|
|
59
61
|
output_lines = []
|
|
60
62
|
output_words = []
|
|
61
63
|
input_lines.each_with_index do |line, rowindex|
|
|
62
64
|
row = []
|
|
63
|
-
line.split(
|
|
65
|
+
line.split(" ").each_with_index do |word, colindex|
|
|
64
66
|
flag = @connectors.include? word.downcase
|
|
65
67
|
|
|
66
68
|
# if <word> is a conector and <pFilter>==true Then Choose this <word>
|
|
@@ -72,7 +74,7 @@ module TextActions
|
|
|
72
74
|
row << word
|
|
73
75
|
end
|
|
74
76
|
end
|
|
75
|
-
row <<
|
|
77
|
+
row << "."
|
|
76
78
|
output_lines << row
|
|
77
79
|
end
|
|
78
80
|
|
|
@@ -103,12 +105,12 @@ module TextActions
|
|
|
103
105
|
lines = input_struct[:lines]
|
|
104
106
|
indexes = input_indexes.sort
|
|
105
107
|
counter = 1
|
|
106
|
-
text =
|
|
108
|
+
text = ""
|
|
107
109
|
|
|
108
110
|
lines.each do |line|
|
|
109
111
|
line.each do |value|
|
|
110
112
|
if value.class == String
|
|
111
|
-
text += (
|
|
113
|
+
text += (" " + value)
|
|
112
114
|
elsif value == value.to_i
|
|
113
115
|
# INFO: ruby 2.4 unifies Fixnum and Bignum into Integer
|
|
114
116
|
# Avoid using deprecated classes.
|
|
@@ -117,14 +119,14 @@ module TextActions
|
|
|
117
119
|
counter += 1
|
|
118
120
|
else
|
|
119
121
|
word = input_struct[:words][value][:word]
|
|
120
|
-
text += (
|
|
122
|
+
text += (" " + word)
|
|
121
123
|
end
|
|
122
124
|
end
|
|
123
125
|
end
|
|
124
126
|
end
|
|
125
|
-
text.gsub!(
|
|
126
|
-
text.gsub!(
|
|
127
|
-
text = text[1, text.size] if text[0] ==
|
|
127
|
+
text.gsub!(" .", ".")
|
|
128
|
+
text.gsub!(" ,", ",")
|
|
129
|
+
text = text[1, text.size] if text[0] == " "
|
|
128
130
|
text
|
|
129
131
|
end
|
|
130
132
|
|
|
@@ -174,20 +176,20 @@ module TextActions
|
|
|
174
176
|
end
|
|
175
177
|
return text if text != input
|
|
176
178
|
|
|
177
|
-
text +
|
|
179
|
+
text + "s"
|
|
178
180
|
end
|
|
179
181
|
|
|
180
182
|
def hide_text(input_text)
|
|
181
183
|
input = input_text.clone
|
|
182
184
|
if count_words(input) < 2 && input.size < 10
|
|
183
|
-
output =
|
|
185
|
+
output = "[*]"
|
|
184
186
|
else
|
|
185
|
-
output =
|
|
187
|
+
output = ""
|
|
186
188
|
input.each_char do |char|
|
|
187
189
|
if ' !|"@#$%&/()=?¿¡+*(){}[],.-_<>'.include? char
|
|
188
190
|
output += char
|
|
189
191
|
else
|
|
190
|
-
output +=
|
|
192
|
+
output += "?"
|
|
191
193
|
end
|
|
192
194
|
end
|
|
193
195
|
end
|