asker-tool 2.1.5 → 2.2.1
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 +13 -17
- data/bin/asker +2 -1
- data/lib/asker/ai/ai.rb +10 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/code/base_code_ai.rb +104 -0
- data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
- data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
- data/lib/asker/ai/code/problem_code_ai.rb +176 -0
- data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
- data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
- data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
- data/lib/asker/ai/concept_ai.rb +13 -3
- data/lib/asker/ai/question.rb +28 -6
- data/lib/asker/ai/stages/base_stage.rb +45 -6
- data/lib/asker/ai/stages/stage_b.rb +100 -50
- data/lib/asker/ai/stages/stage_d.rb +75 -90
- data/lib/asker/ai/stages/stage_f.rb +64 -36
- data/lib/asker/ai/stages/stage_i.rb +79 -92
- data/lib/asker/ai/stages/stage_s.rb +41 -36
- data/lib/asker/ai/stages/stage_t.rb +149 -108
- data/lib/asker/application.rb +19 -11
- data/lib/asker/cli.rb +31 -44
- data/lib/asker/data/code.rb +62 -0
- data/lib/asker/data/column.rb +31 -21
- data/lib/asker/data/concept.rb +109 -65
- data/lib/asker/data/data_field.rb +14 -0
- data/lib/asker/data/project_data.rb +63 -0
- data/lib/asker/data/row.rb +75 -52
- data/lib/asker/data/table.rb +91 -42
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +51 -35
- data/lib/asker/displayer/code_displayer.rb +7 -0
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +74 -53
- data/lib/asker/displayer/concept_displayer.rb +16 -9
- data/lib/asker/displayer/stats_displayer.rb +12 -3
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +19 -11
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +13 -6
- data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +9 -6
- data/lib/asker/files/{config.ini → asker.ini} +48 -1
- data/lib/asker/files/example-concept.haml +0 -1
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/{lang/locales/fr → files/language/du}/mistakes.yaml +1 -1
- data/lib/asker/files/language/du/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
- data/lib/asker/files/language/en/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
- data/lib/asker/files/language/es/mistakes.yaml +84 -0
- data/lib/asker/files/language/es/templates.yaml +29 -0
- data/lib/asker/files/language/fr/connectors.yaml +76 -0
- data/lib/asker/{lang/locales/es → files/language/fr}/mistakes.yaml +0 -0
- data/lib/asker/files/language/fr/templates.yaml +29 -0
- data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
- data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
- data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
- data/lib/asker/formatter/concept_string_formatter.rb +7 -4
- data/lib/asker/formatter/moodle/matching.erb +38 -0
- data/lib/asker/formatter/moodle/multichoice.erb +49 -0
- data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
- data/lib/asker/formatter/moodle/truefalse.erb +47 -0
- data/lib/asker/formatter/question_gift_formatter.rb +30 -20
- data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
- data/lib/asker/{checker.rb → input_checker.rb} +126 -49
- data/lib/asker/lang/lang.rb +17 -10
- data/lib/asker/lang/lang_factory.rb +32 -5
- data/lib/asker/lang/text_actions.rb +87 -69
- data/lib/asker/loader/code_loader.rb +4 -4
- data/lib/asker/loader/content_loader.rb +21 -19
- data/lib/asker/loader/directory_loader.rb +1 -8
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +3 -14
- data/lib/asker/loader/haml_loader.rb +15 -0
- data/lib/asker/loader/image_url_loader.rb +8 -12
- data/lib/asker/loader/input_loader.rb +13 -15
- data/lib/asker/loader/project_loader.rb +25 -15
- data/lib/asker/logger.rb +36 -9
- data/lib/asker/skeleton.rb +23 -13
- data/lib/asker.rb +76 -42
- metadata +53 -54
- data/lib/asker/code/ai/base_code_ai.rb +0 -48
- data/lib/asker/code/code.rb +0 -53
- data/lib/asker/lang/locales/du/templates.yaml +0 -50
- data/lib/asker/lang/locales/en/templates.yaml +0 -29
- data/lib/asker/lang/locales/es/templates.yaml +0 -29
- data/lib/asker/lang/locales/fr/connectors.yaml +0 -92
- data/lib/asker/lang/locales/fr/templates.yaml +0 -29
- data/lib/asker/project.rb +0 -172
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -12,12 +12,11 @@ module ConceptStringFormatter
|
|
|
12
12
|
def self.to_s(concept)
|
|
13
13
|
tt = Terminal::Table.new
|
|
14
14
|
get_tt_rows(concept).each { |row| tt.add_row row }
|
|
15
|
-
|
|
15
|
+
tt.to_s
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# rubocop:disable Metrics/AbcSize
|
|
19
19
|
# rubocop:disable Metrics/MethodLength
|
|
20
|
-
# rubocop:disable Layout/LineLength
|
|
21
20
|
private_class_method def self.get_tt_rows(concept)
|
|
22
21
|
rows = []
|
|
23
22
|
rows << [Rainbow(concept.id.to_s).bright,
|
|
@@ -31,13 +30,17 @@ module ConceptStringFormatter
|
|
|
31
30
|
rows << [Rainbow('Referenced by').blue,
|
|
32
31
|
concept.referenced_by.join(', ')[0...70].to_s]
|
|
33
32
|
rows << format_texts(concept)
|
|
34
|
-
|
|
33
|
+
unless concept.images.size.zero?
|
|
34
|
+
counter1 = 0
|
|
35
|
+
concept.images.each { |image| counter1 += 1 if image[:file] == :none }
|
|
36
|
+
counter2 = concept.images.size - counter1
|
|
37
|
+
rows << [Rainbow('.def(images)').blue, "#{counter1} text / #{counter2} file"]
|
|
38
|
+
end
|
|
35
39
|
rows << format_tables(concept) unless concept.tables.count.zero?
|
|
36
40
|
rows << format_neighbors(concept)
|
|
37
41
|
end
|
|
38
42
|
# rubocop:enable Metrics/AbcSize
|
|
39
43
|
# rubocop:enable Metrics/MethodLength
|
|
40
|
-
# rubocop:enable Layout/LineLength
|
|
41
44
|
|
|
42
45
|
private_class_method def self.format_texts(concept)
|
|
43
46
|
list = []
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
|
2
|
+
<!-- question: <%= question.comment %> -->
|
|
3
|
+
<% end %>
|
|
4
|
+
<question type="matching">
|
|
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
|
+
<shuffleanswers>true</shuffleanswers>
|
|
21
|
+
<correctfeedback format="html">
|
|
22
|
+
<text></text>
|
|
23
|
+
</correctfeedback>
|
|
24
|
+
<partiallycorrectfeedback format="html">
|
|
25
|
+
<text></text>
|
|
26
|
+
</partiallycorrectfeedback>
|
|
27
|
+
<incorrectfeedback format="html">
|
|
28
|
+
<text></text>
|
|
29
|
+
</incorrectfeedback>
|
|
30
|
+
<% question.matching.each do |i, j| %>
|
|
31
|
+
<subquestion format="html">
|
|
32
|
+
<text><![CDATA[<%= i %>]]></text>
|
|
33
|
+
<answer>
|
|
34
|
+
<text><![CDATA[<%= j %>]]></text>
|
|
35
|
+
</answer>
|
|
36
|
+
</subquestion>
|
|
37
|
+
<% end %>
|
|
38
|
+
</question>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
|
2
|
+
<!-- question: <%= question.comment %> -->
|
|
3
|
+
<% end %>
|
|
4
|
+
<question type="multichoice">
|
|
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
|
+
<single>true</single>
|
|
21
|
+
<shuffleanswers>true</shuffleanswers>
|
|
22
|
+
<answernumbering>abc</answernumbering>
|
|
23
|
+
<correctfeedback format="html">
|
|
24
|
+
<text></text>
|
|
25
|
+
</correctfeedback>
|
|
26
|
+
<partiallycorrectfeedback format="html">
|
|
27
|
+
<text></text>
|
|
28
|
+
</partiallycorrectfeedback>
|
|
29
|
+
<incorrectfeedback format="html">
|
|
30
|
+
<text></text>
|
|
31
|
+
</incorrectfeedback>
|
|
32
|
+
<answer fraction="100" format="html">
|
|
33
|
+
<text><%= question.good %></text>
|
|
34
|
+
<feedback format="html">
|
|
35
|
+
<text></text>
|
|
36
|
+
</feedback>
|
|
37
|
+
</answer>
|
|
38
|
+
<%
|
|
39
|
+
question.bads.shuffle! if question.shuffle?
|
|
40
|
+
question.bads.each do |i|
|
|
41
|
+
%>
|
|
42
|
+
<answer fraction="<%= penalty %>" format="html">
|
|
43
|
+
<text><![CDATA[<%= i %>]]></text>
|
|
44
|
+
<feedback format="html">
|
|
45
|
+
<text></text>
|
|
46
|
+
</feedback>
|
|
47
|
+
</answer>
|
|
48
|
+
<% end %>
|
|
49
|
+
</question>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
|
2
|
+
<!-- question: <%= question.comment %> -->
|
|
3
|
+
<% end %>
|
|
4
|
+
<question type="shortanswer">
|
|
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
|
+
<usecase>0</usecase>
|
|
21
|
+
<% question.shorts.uniq! %>
|
|
22
|
+
<% question.shorts.each do |i| %>
|
|
23
|
+
<answer fraction="100" format="moodle_auto_format">
|
|
24
|
+
<text><![CDATA[<%= i %>]]></text>
|
|
25
|
+
<feedback format="html">
|
|
26
|
+
<text></text>
|
|
27
|
+
</feedback>
|
|
28
|
+
</answer>
|
|
29
|
+
<% end %>
|
|
30
|
+
</question>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
|
2
|
+
<!-- question: <%= question.comment %> -->
|
|
3
|
+
<% end %>
|
|
4
|
+
<question type="truefalse">
|
|
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>1.0000000</penalty>
|
|
19
|
+
<hidden>0</hidden>
|
|
20
|
+
<% if question.good == 'TRUE' %>
|
|
21
|
+
<answer fraction="100" format="moodle_auto_format">
|
|
22
|
+
<text>true</text>
|
|
23
|
+
<feedback format="html">
|
|
24
|
+
<text></text>
|
|
25
|
+
</feedback>
|
|
26
|
+
</answer>
|
|
27
|
+
<answer fraction="0" format="moodle_auto_format">
|
|
28
|
+
<text>false</text>
|
|
29
|
+
<feedback format="html">
|
|
30
|
+
<text></text>
|
|
31
|
+
</feedback>
|
|
32
|
+
</answer>
|
|
33
|
+
<% else %>
|
|
34
|
+
<answer fraction="0" format="moodle_auto_format">
|
|
35
|
+
<text>true</text>
|
|
36
|
+
<feedback format="html">
|
|
37
|
+
<text></text>
|
|
38
|
+
</feedback>
|
|
39
|
+
</answer>
|
|
40
|
+
<answer fraction="100" format="moodle_auto_format">
|
|
41
|
+
<text>false</text>
|
|
42
|
+
<feedback format="html">
|
|
43
|
+
<text></text>
|
|
44
|
+
</feedback>
|
|
45
|
+
</answer>
|
|
46
|
+
<% end %>
|
|
47
|
+
</question>
|
|
@@ -1,63 +1,73 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: false
|
|
2
2
|
|
|
3
3
|
# Transform Questions into Gift format
|
|
4
4
|
module QuestionGiftFormatter
|
|
5
|
+
##
|
|
6
|
+
# Convert question object into gift formatted string
|
|
7
|
+
# @param question (Question)
|
|
8
|
+
# @return String
|
|
5
9
|
def self.to_s(question)
|
|
6
|
-
|
|
10
|
+
s = ''
|
|
11
|
+
return s unless question.encode == :none
|
|
12
|
+
|
|
7
13
|
# Return question using gift format
|
|
8
|
-
cond =
|
|
9
|
-
s = "// #{
|
|
10
|
-
s << "::#{
|
|
14
|
+
cond = question.comment.nil? || question.comment.empty?
|
|
15
|
+
s = "// #{question.comment}\n" unless cond
|
|
16
|
+
s << "::#{question.name}::[html]#{sanitize(question.text)}\n"
|
|
11
17
|
|
|
12
|
-
case
|
|
18
|
+
case question.type
|
|
13
19
|
when :choice
|
|
14
20
|
s += "{\n"
|
|
15
|
-
a = [" =#{sanitize(
|
|
21
|
+
a = [" =#{sanitize(question.good)}\n"]
|
|
16
22
|
penalties = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
|
|
17
|
-
penalty = penalties[
|
|
23
|
+
penalty = penalties[question.bads.size]
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
a.shuffle! if
|
|
25
|
+
question.bads.each { |i| a << (" ~#{penalty}" + sanitize(i) + "\n") }
|
|
26
|
+
a.shuffle! if question.shuffle?
|
|
21
27
|
a.each do |i|
|
|
22
28
|
text = i
|
|
23
29
|
text = i[0, 220] + '...(ERROR: text too long)' if text.size > 255
|
|
24
30
|
s << text
|
|
25
31
|
end
|
|
26
|
-
s += " #####{sanitize(
|
|
32
|
+
s += " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
|
|
27
33
|
s += "}\n\n"
|
|
28
34
|
when :boolean
|
|
29
|
-
s << "{#{
|
|
35
|
+
s << "{#{question.good}#####{sanitize(question.feedback.to_s)}}\n\n"
|
|
30
36
|
when :match
|
|
31
37
|
s << "{\n"
|
|
32
38
|
a = []
|
|
33
|
-
|
|
39
|
+
question.matching.each do |i, j|
|
|
34
40
|
i = i[0, 220] + '...(ERROR: text too long)' if i.size > 255
|
|
35
41
|
j = j[0, 220] + '...(ERROR: text too long)' if j.size > 255
|
|
36
42
|
a << " =#{sanitize(i)} -> #{sanitize(j)}\n"
|
|
37
43
|
end
|
|
38
|
-
a.shuffle! if
|
|
44
|
+
a.shuffle! if question.shuffle?
|
|
39
45
|
a.each { |i| s << i }
|
|
40
46
|
s << "}\n\n"
|
|
41
47
|
when :short
|
|
42
48
|
s << "{\n"
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
question.shorts.uniq!
|
|
50
|
+
question.shorts.each do |i|
|
|
45
51
|
text = i
|
|
46
52
|
text = i[0, 220] + '...(ERROR: too long)' if text.size > 255
|
|
47
53
|
s << " =%100%#{text}#\n"
|
|
48
54
|
end
|
|
49
|
-
s << " #####{sanitize(
|
|
55
|
+
s << " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
|
|
50
56
|
s << "}\n\n"
|
|
51
57
|
end
|
|
52
58
|
s
|
|
53
59
|
end
|
|
54
60
|
|
|
61
|
+
##
|
|
62
|
+
# Sanitize gift text
|
|
63
|
+
# @param input (String)
|
|
64
|
+
# @return String
|
|
55
65
|
def self.sanitize(input = '')
|
|
56
66
|
output = input.dup
|
|
57
|
-
output.gsub!(
|
|
67
|
+
output.gsub!('#', '\#')
|
|
58
68
|
output.gsub!("\n", " ")
|
|
59
|
-
|
|
60
|
-
output.gsub!(
|
|
69
|
+
output.gsub!(':', '\:')
|
|
70
|
+
output.gsub!('=', '\=')
|
|
61
71
|
output.gsub!("\{", "\\{")
|
|
62
72
|
output.gsub!("\}", "\\}")
|
|
63
73
|
output
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
|
|
5
|
+
# Transform Questions into Gift format
|
|
6
|
+
module QuestionMoodleFormatter
|
|
7
|
+
##
|
|
8
|
+
# Convert question object into gift formatted string
|
|
9
|
+
# @param question (Question)
|
|
10
|
+
# @return String
|
|
11
|
+
def self.to_s(question)
|
|
12
|
+
case question.type
|
|
13
|
+
when :choice
|
|
14
|
+
penalties = ['', '-50', '-33.33333', '-25', '-20']
|
|
15
|
+
penalty = penalties[question.bads.size]
|
|
16
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'multichoice.erb'))
|
|
17
|
+
when :boolean
|
|
18
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'truefalse.erb'))
|
|
19
|
+
when :match
|
|
20
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'matching.erb'))
|
|
21
|
+
when :short
|
|
22
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'shortanswer.erb'))
|
|
23
|
+
end
|
|
24
|
+
renderer = ERB.new(template)
|
|
25
|
+
renderer.result(binding)
|
|
26
|
+
end
|
|
27
|
+
end
|