asciidoctor-moodle 1.0.0.dev

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.
@@ -0,0 +1,163 @@
1
+ require_relative '../extensions'
2
+ #Gras et italique fonctionnent pour les questions
3
+ module Asciidoctor
4
+ module Question
5
+
6
+ class NumericalBlockProcessor < Extensions::BaseProcessor
7
+
8
+ def prepare_unit(unit)
9
+ units = Array.new
10
+ regex = %r{([^,]+?),}
11
+ matchData = regex.match(unit)
12
+ begin
13
+ units.push matchData.captures[0]
14
+ unit.gsub!(matchData.captures[0],"")
15
+ matchData = regex.match(unit)
16
+ end while matchData != nil
17
+
18
+ units.push(unit[1..unit.size])
19
+ end
20
+
21
+
22
+ def process(parent, source, tag)
23
+
24
+ docName = parent.attributes['docname']
25
+ id = tag[:id]
26
+ err = '+++ You need an answer [question, num, ans=5]+++'
27
+ unit = tag["unit"]
28
+ ans= tag["ans"]
29
+ tolerance=tag["tolerance"]
30
+ copyUnit = unit.dup
31
+
32
+ question = source.lines
33
+ question = "<p>" << question.join("</p> <p>")
34
+ question << "</p>"
35
+
36
+
37
+
38
+ new_parent = Asciidoctor::Block.new parent, :open, {:attributes => {'id' => "#{docName}_question_#{id}_numerical"}}
39
+
40
+ question_string = prepare_question_lines(question, docName,id)
41
+
42
+ tolerance = 0 if !tolerance
43
+
44
+ if (unit != nil)
45
+ unit = prepare_unit(copyUnit)
46
+ answer_string = prepare_answer_lines_with_unit(ans,tolerance,unit)
47
+ else
48
+ answer_string = prepare_answer_lines(ans,tolerance)
49
+ end
50
+
51
+ questAns = "#{question_string} \n #{answer_string}"
52
+
53
+ if ans != nil
54
+ reader = Asciidoctor::Reader.new(questAns)
55
+ loop do
56
+ block = Asciidoctor::Parser.next_block reader, new_parent
57
+ break if block.nil?
58
+ new_parent.blocks.push block
59
+ end
60
+ else
61
+ process_error_push new_parent, err, answers
62
+ end
63
+ new_parent
64
+
65
+ end
66
+
67
+ def prepare_answer_lines(lines)
68
+ lines
69
+ end
70
+
71
+ def prepare_answers(answers_block, tag)
72
+ answers_block.blocks.shuffle! if tag[:shuffle] == 'shuffle'
73
+ answers_block
74
+ end
75
+
76
+ end
77
+
78
+
79
+ class MOODLENumericalBlockProcessor < NumericalBlockProcessor
80
+
81
+ def prepare_answer_lines(answer, tolerance)
82
+ preAns="+++ <answer fraction=\"100\" format=\"moodle_auto_format\">
83
+ <text>+++"
84
+ postAns="+++ </text>
85
+ <feedback format=\"html\">
86
+ <text></text>
87
+ </feedback>
88
+ <tolerance>#{tolerance}</tolerance>
89
+ </answer>
90
+ <unitgradingtype>0</unitgradingtype>
91
+ <unitpenalty>0.1000000</unitpenalty>
92
+ <showunits>3</showunits>
93
+ <unitsleft>0</unitsleft>
94
+ </question> +++"
95
+ answer_string = "#{preAns} #{answer} #{postAns}"
96
+
97
+ end
98
+
99
+ def prepare_answer_lines_with_unit(answer, tolerance, units)
100
+ preAns="+++ <answer fraction=\"100\" format=\"moodle_auto_format\">
101
+ <text>#{answer}</text>
102
+ <feedback format=\"html\">
103
+ <text></text>
104
+ </feedback>
105
+ <tolerance>#{tolerance}</tolerance>
106
+ </answer>"
107
+ postAns =" <unitgradingtype>1</unitgradingtype>
108
+ <unitpenalty>0.5000000</unitpenalty>
109
+ <showunits>1</showunits>
110
+ <unitsleft>0</unitsleft>
111
+ </question> +++"
112
+ textUnits="<units> \n"
113
+
114
+
115
+ units.each do |item|
116
+ regex1 = %r{(.*)=}
117
+ matchData1 = regex1.match(item)
118
+ regex2 = %r{=(.*)}
119
+ matchData2 = regex2.match(item)
120
+ unit = matchData1.captures[0]
121
+ multiplier = matchData2.captures[0]
122
+ textUnits << "<unit>
123
+ <multiplier>#{multiplier}</multiplier>
124
+ <unit_name>#{unit}</unit_name>
125
+ </unit>"
126
+ end
127
+
128
+ textUnits << "</units>"
129
+
130
+ answer_string = "#{preAns} #{textUnits} #{postAns}"
131
+
132
+
133
+ end
134
+
135
+ def prepare_question_lines(question, docName,id)
136
+
137
+ preQuest = "+++ <question type=\"numerical\">
138
+ <name>
139
+ <text>#{docName}_question_#{id}_numerical</text>
140
+ </name>
141
+ <questiontext format=\"html\">
142
+ <text><![CDATA[<p>"
143
+ postQuest = "</p>]]></text>
144
+ </questiontext>
145
+ <generalfeedback format=\"html\">
146
+ <text></text>
147
+ </generalfeedback>
148
+ <defaultgrade>1</defaultgrade>
149
+ <penalty>0.3333333</penalty>
150
+ <hidden>0</hidden>
151
+ <idnumber></idnumber> +++"
152
+
153
+ string_question = "#{preQuest} #{question} #{postQuest}"
154
+
155
+ string_question
156
+ end
157
+
158
+
159
+
160
+
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,113 @@
1
+ require_relative '../extensions'
2
+ #Gras et italique fonctionnent pour les questions
3
+ module Asciidoctor
4
+ module Question
5
+
6
+ class OrderingBlockProcessor < Extensions::BaseProcessor
7
+
8
+
9
+ def process(parent, source, tag)
10
+
11
+ docName = parent.attributes['docname']
12
+ id = tag[:id]
13
+ err = '+++ You need at least 2 answers in the list +++'
14
+ lines = source.lines
15
+ new_parent = Asciidoctor::Block.new parent, :open, {:attributes => {'id' => "#{docName}_question_#{id}_ordering"}}
16
+
17
+ blockQ = Asciidoctor::Parser.next_block source, new_parent
18
+ listA = Asciidoctor::Parser.next_block source, new_parent
19
+
20
+
21
+ answers = Array.new
22
+ listA.items.each do |item|
23
+ answers.push item.text
24
+ end
25
+ nbAns = answers.size
26
+ question_string = prepare_question_lines(blockQ.content, docName,id, nbAns)
27
+ answer_string = prepare_answer_lines answers
28
+
29
+ questAns = "#{question_string} \n #{answer_string}"
30
+
31
+ if answers.size >= 2
32
+ reader = Asciidoctor::Reader.new(questAns)
33
+ loop do
34
+ block = Asciidoctor::Parser.next_block reader, new_parent
35
+ break if block.nil?
36
+ new_parent.blocks.push block
37
+ end
38
+ else
39
+ process_error_push new_parent, err, answers
40
+ end
41
+ new_parent
42
+
43
+ end
44
+
45
+ def prepare_answer_lines(lines)
46
+ lines
47
+ end
48
+
49
+ def prepare_answers(answers_block, tag)
50
+ answers_block.blocks.shuffle! if tag[:shuffle] == 'shuffle'
51
+ answers_block
52
+ end
53
+
54
+ end
55
+
56
+
57
+ class MOODLEOrderingBlockProcessor < OrderingBlockProcessor
58
+
59
+ def prepare_answer_lines(answers)
60
+ text=""
61
+ nbAns = answers.size
62
+
63
+ nbAns.times do |i|
64
+ frac = i+1
65
+ text << "<answer fraction=\"#{frac}\" format=\"moodle_auto_format\">
66
+ <text>#{answers[i]}</text>
67
+ </answer> \n"
68
+ end
69
+ text << "</question> +++"
70
+
71
+ end
72
+
73
+ def prepare_question_lines(question, docName,id,nbAns)
74
+
75
+ preQuest = "+++ <question type=\"ordering\">
76
+ <name>
77
+ <text>#{docName}_question_#{id}_ordering</text>
78
+ </name>
79
+ <questiontext format=\"html\">
80
+ <text><![CDATA[<p>"
81
+ postQuest = "</p>]]></text>
82
+ </questiontext>
83
+ <generalfeedback format=\"html\">
84
+ <text></text>
85
+ </generalfeedback>
86
+ <defaultgrade>1</defaultgrade>
87
+ <penalty>0.3333333</penalty>
88
+ <hidden>0</hidden>
89
+ <idnumber></idnumber>
90
+ <layouttype></layouttype>
91
+ <selecttype></selecttype>
92
+ <selectcount>#{nbAns}</selectcount>
93
+ <gradingtype></gradingtype>
94
+ <showgrading></showgrading>
95
+ <numberingstyle>none</numberingstyle>
96
+ <correctfeedback format=\"html\">
97
+ <text><![CDATA[<p>Your answer is correct.</p>]]></text>
98
+ </correctfeedback>
99
+ <partiallycorrectfeedback format=\"html\">
100
+ <text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
101
+ </partiallycorrectfeedback>
102
+ <incorrectfeedback format=\"html\">
103
+ <text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
104
+ </incorrectfeedback>
105
+ <shownumcorrect>1</shownumcorrect>"
106
+
107
+ string_question = "#{preQuest} #{question} #{postQuest}"
108
+
109
+ string_question
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,113 @@
1
+
2
+ require_relative '../extensions'
3
+ require_relative '../multiple_choice/extension'
4
+ require_relative '../gap/extension'
5
+ require_relative '../true_false/extension'
6
+ require_relative '../cloze_mc/extension'
7
+ require_relative '../matching/extension'
8
+ require_relative '../ordering/extension'
9
+ require_relative '../drag_drop_text and missing_words/extension'
10
+ require_relative '../short/extension'
11
+ require_relative '../numerical/extension'
12
+
13
+
14
+ module Asciidoctor
15
+ module Question
16
+ class QuestionBlockProcessor < Extensions::BaseProcessor
17
+ name_positional_attributes :type
18
+
19
+ def initialize name = nil, config = {}
20
+ super name, config
21
+ @id = 0
22
+ end
23
+
24
+ def process(parent, source, tag)
25
+
26
+ block = nil
27
+ err = nil
28
+ new_tag = tag.dup
29
+ doc = parent.document
30
+
31
+ doc.attributes['question-id-seq'] ||= 0
32
+ doc.attributes['question-id-seq'] += 1
33
+
34
+ type = new_tag[:type]
35
+ new_tag[:id] = doc.attributes['question-id-seq']
36
+ new_tag[:solution] = !parent.attributes['solution'].nil?
37
+
38
+ if type.nil?
39
+ err = 'Type\'s error'
40
+ end
41
+
42
+ if err.nil?
43
+
44
+ if type == 'mc' or type =="MC"
45
+ block = process_question_mc parent, source, new_tag
46
+ elsif type == 'gap'
47
+ block = process_question_gap parent, source, new_tag
48
+ elsif type == 'TF' or type == 'tf'
49
+ block = process_question_tf parent, source, new_tag
50
+ elsif type == 'CMC' or type == 'cmc'
51
+ block = process_question_cmc parent, source, new_tag
52
+ elsif type == 'Matching' or type == 'matching' or type == 'match' or type == 'Match'
53
+ block = process_question_matching parent, source, new_tag
54
+ elsif type == 'Ordering' or type == 'ordering' or type == 'order' or type == 'Order'
55
+ block = process_question_ordering parent, source, new_tag
56
+ elsif type == 'DDT' or type == 'ddt' or type =="mw" or type=="MW"
57
+ block = process_question_ddt parent, source, new_tag
58
+ elsif type == 'short' or type == 'Short'
59
+ block = process_question_short parent, source, new_tag
60
+ elsif type == 'num' or type == 'Num'
61
+ block = process_question_num parent, source, new_tag
62
+ end
63
+ else
64
+ block = process_error parent, err, source.lines
65
+ end
66
+ block
67
+ end
68
+ end
69
+
70
+
71
+
72
+ class MOODLEQuestionBlockProcessor < QuestionBlockProcessor
73
+ name_positional_attributes :type
74
+
75
+ def process_question_mc parent, source, tag
76
+ MOODLEMultipleChoiceBlockProcessor.new.process parent, source, tag
77
+ end
78
+
79
+ def process_question_gap parent, source, tag
80
+ MOODLEGAPBlockProcessor.new.process parent, source, tag
81
+ end
82
+
83
+ def process_question_tf parent, source, tag
84
+ MOODLETrueFalseBlockProcessor.new.process parent, source, tag
85
+ end
86
+
87
+ def process_question_cmc parent, source, tag
88
+ MOODLEClozeMCBlockProcessor.new.process parent, source, tag
89
+ end
90
+
91
+ def process_question_matching parent, source, tag
92
+ MOODLEMatchingBlockProcessor.new.process parent, source, tag
93
+ end
94
+
95
+ def process_question_ordering parent, source, tag
96
+ MOODLEOrderingBlockProcessor.new.process parent, source, tag
97
+ end
98
+
99
+ def process_question_ddt parent, source, tag
100
+ MOODLEDDTAndMWBlockProcessor.new.process parent, source, tag
101
+ end
102
+
103
+ def process_question_short parent, source, tag
104
+ MOODLESHORTBlockProcessor.new.process parent, source, tag
105
+ end
106
+
107
+ def process_question_num parent, source, tag
108
+ MOODLENumericalBlockProcessor.new.process parent, source, tag
109
+ end
110
+
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'extensions'
2
+
3
+ Asciidoctor::Extensions.register do
4
+ require_relative 'question/extension'
5
+ block Asciidoctor::Question::MOODLEQuestionBlockProcessor, :question if document.backend == 'moodle'
6
+ end
@@ -0,0 +1,102 @@
1
+ require_relative '../extensions'
2
+ #Italique et gras pour les question ok
3
+ module Asciidoctor
4
+ module Question
5
+
6
+ class ShortBlockProcessor < Extensions::BaseProcessor
7
+
8
+ def process(parent, source, tag)
9
+ docName = parent.attributes['docname']
10
+
11
+ if tag["case"]
12
+ isCaseSensitive = 1
13
+ else
14
+ isCaseSensitive = 0
15
+ end
16
+
17
+ id = tag[:id]
18
+ question= source.lines.join("\n")
19
+
20
+ err = 'Wrong format : start your question by [question, short, the-answer] or by [question, short, the-answer, case=case] for being case sensitive'
21
+ answer = Array.new
22
+ answer.push(tag[3])
23
+ question = prepare_question_lines(question, docName, id, isCaseSensitive)
24
+ answer = prepare_answer_lines(answer)
25
+
26
+ new_parent = Asciidoctor::Block.new parent, :open, {:attributes => {'id' => "#{docName}_question_#{id}_short"}}
27
+
28
+ reader = Asciidoctor::Reader.new(question)
29
+ loop do
30
+ block = Asciidoctor::Parser.next_block reader, new_parent
31
+ break if block.nil?
32
+ new_parent.blocks.push block
33
+ end
34
+
35
+ reader = Asciidoctor::Reader.new(answer)
36
+ answers_block = Asciidoctor::Parser.next_block reader, new_parent
37
+ new_parent.blocks.push answers_block
38
+ post_answers new_parent, tag
39
+ new_parent
40
+ end
41
+
42
+
43
+ def prepare_answer_lines(lines)
44
+ lines
45
+ end
46
+
47
+ def prepare_answers(answers_block, tag)
48
+ answers_block
49
+ end
50
+
51
+ end
52
+
53
+
54
+
55
+ class MOODLESHORTBlockProcessor < ShortBlockProcessor
56
+
57
+
58
+ def prepare_question_lines(lines, docName,id,isCaseSensitive)
59
+
60
+ preQuest = "+++ <question type=\"shortanswer\">
61
+ <name>
62
+ <text> #{docName}_question_#{id}_short </text>
63
+ </name>
64
+ <questiontext format=\"html\">
65
+ <text><![CDATA[ +++"
66
+ postQuest = "+++ ]]></text>
67
+ </questiontext>
68
+ <generalfeedback format=\"html\">
69
+ <text></text>
70
+ </generalfeedback>
71
+ <defaultgrade>1</defaultgrade>
72
+ <penalty>0.3333333</penalty>
73
+ <hidden>0</hidden>
74
+ <idnumber></idnumber>
75
+ <usecase>#{isCaseSensitive}</usecase> +++"
76
+
77
+ preQuest << lines
78
+ preQuest << postQuest
79
+ [preQuest]
80
+ end
81
+
82
+ def prepare_answer_lines(answer)
83
+ preAns ="<answer fraction=\"100\" format=\"moodle_auto_format\">
84
+ <text>"
85
+ postAns = "</text>
86
+ <feedback format=\"html\">
87
+ <text></text>
88
+ </feedback>
89
+ </answer>
90
+ </question>"
91
+
92
+ answer.prepend("+++")
93
+ answer.prepend(preAns)
94
+ answer.prepend("+++")
95
+ answer.push("+++")
96
+ answer.push(postAns)
97
+ answer.push("+++")
98
+ answer
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,97 @@
1
+ require_relative '../extensions'
2
+ #Italique et gras pour les question ok
3
+ module Asciidoctor
4
+ module Question
5
+
6
+ class TrueFalseBlockProcessor < Extensions::BaseProcessor
7
+
8
+ def process(parent, source, tag)
9
+ docName = parent.attributes['docname']
10
+ id = tag[:id]
11
+
12
+ err = 'Wrong format : start your question by [question, TF, true] or by [question, TF,false]'
13
+ answers = Array.new ['[options=interactive]']
14
+ question = Array.new
15
+ answer = tag[3]
16
+ source.lines.each { |line| question.push line}
17
+
18
+ new_parent = Asciidoctor::Block.new parent, :open, {:attributes => {'id' => "#{docName}_question_#{id}_tf"}}
19
+
20
+
21
+ if answer != 'True' && answer != 'true' && answer != 'T' && answer != 'False' && answer != 'false' && answer != 'F'
22
+ process_error_push new_parent, err, answers
23
+ else
24
+ question = prepare_question_lines(question, docName,id,answer)
25
+ reader = Asciidoctor::Reader.new(question)
26
+ loop do
27
+ block = Asciidoctor::Parser.next_block reader, new_parent
28
+
29
+ break if block.nil?
30
+ new_parent.blocks.push block
31
+ end
32
+ end
33
+ new_parent
34
+ end
35
+
36
+
37
+ def prepare_answer_lines(lines)
38
+ lines
39
+ end
40
+
41
+ def prepare_answers(answers_block, tag)
42
+ answers_block
43
+ end
44
+
45
+ end
46
+
47
+
48
+
49
+ class MOODLETrueFalseBlockProcessor < TrueFalseBlockProcessor
50
+
51
+ def prepare_question_lines(lines, docName,id, answer)
52
+ if answer == 'True' || answer == 'true' || answer == 'T'
53
+ answer, notAnswer = 'true','false'
54
+ else
55
+ answer, notAnswer = 'false','true'
56
+ end
57
+
58
+ preQuest = " <question type=\"truefalse\">
59
+ <name>
60
+ <text> #{docName}_question_#{id}_tf </text>
61
+ </name>
62
+ <questiontext format=\"html\">
63
+ <text><![CDATA[<p> "
64
+ posQuest = " ]]></text>
65
+ </questiontext>
66
+ <generalfeedback format=\"html\">
67
+ <text></text>
68
+ </generalfeedback>
69
+ <defaultgrade>1</defaultgrade>
70
+ <penalty>1</penalty>
71
+ <hidden>0</hidden>
72
+ <idnumber></idnumber>
73
+ <answer fraction=\"100\" format=\"moodle_auto_format\">
74
+ <text>#{answer}</text>
75
+ <feedback format=\"html\">
76
+ <text></text>
77
+ </feedback>
78
+ </answer>
79
+ <answer fraction=\"0\" format=\"moodle_auto_format\">
80
+ <text>#{notAnswer}</text>
81
+ <feedback format=\"html\">
82
+ <text></text>
83
+ </feedback>
84
+ </answer>
85
+ </question> "
86
+
87
+ lines.prepend("+++")
88
+ lines.prepend(preQuest)
89
+ lines.prepend("+++")
90
+ lines.push("+++")
91
+ lines.push(posQuest)
92
+ lines.push("+++")
93
+ lines
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ module Asciidoctor
3
+ module Moodle
4
+ VERSION = '1.0.0.dev'
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ # frozen_string_literal: true
3
+ #require 'asciidoctor' unless defined? Asciidoctor.load
4
+ require_relative 'asciidoctor-moodle/converter'
5
+ #require_relative 'asciidoctor-moodle/question/extension'
6
+ require_relative 'asciidoctor-moodle/question'