-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathse350-question-writer
executable file
·100 lines (85 loc) · 3.77 KB
/
se350-question-writer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env ruby
require 'rubygems'
require 'json'
require 'erb'
require 'tmpdir'
# Check for official validator
def validator?; system('which question-validator > /dev/null 2>&1'); end
if !validator?
$stderr.puts("WARNING: Did not detect 'official' validator installed on your system. This script " +
"WILL work but, to be safe, you should probably install it from " +
"https://github.com/jcpetkovich/App-QuestionValidator/.")
end
# First, we extract the input from stdin
$stderr.puts("Reading input...")
input = $stdin.read
questions = JSON.parse(input, :symbolize_names => true)
$stderr.puts("Validating input...")
raise 'Questions must be provided as a JSON array' unless questions.is_a?(Array)
$stderr.puts 'WARNING: You should submit 4 questions' unless questions.length == 4
# Turn each JSON question into a d2l question
outputs = []
questions.each_with_index do |question, index|
# Validate all required question fields are present
$stderr.puts("\nValidating question #{index}...")
[:title, :question, :options].each do |field|
raise "'#{field}' field must be non-null for questions" if question[field].nil?
end
# Validating all required option fields are present
question[:options].each do |option|
[:points, :answer].each do |field|
raise "'#{field}' field must be non-null for options" if option[field].nil?
end
end
# All questions must be multiple choice questions with four possible answers.
raise "You must provide exactly 4 options for each question" unless question[:options].length == 4
# Ensure all point values are integers between 0 and 100
raise "All option 'point' values must be integers" unless question[:options].count {|o| !(0..100).include?(o[:points])} == 0
# At most one answer must give full points.
raise "Exactly one option must give 100 points" unless question[:options].count {|o| o[:points] == 100} == 1
# At least two answers must give zero points.
raise "At least two options must give 0 points" unless question[:options].count {|o| o[:points] == 0} >= 2
# One question may give zero to fifty percent of the points.
raise "At most one option may give 1 to 50 points" unless question[:options].count {|o| (1..50).include?(o[:points])} <= 1
# This is the template required for the d2l import
def escape(input); input.to_s.gsub('"', '\\"'); end
template = ERB.new <<-eos
NewQuestion,MC,
Title,"<%=escape question[:title] %>",
QuestionText,"\n<%=escape question[:question] %>\n",
<% question[:options].each do |option| %><%#
%>Option,<%= option[:points] %>,"<%=escape option[:answer] %>",,"<%=escape option[:feedback] %>"
<% end %><%#
%>Feedback,"<%=escape question[:feedback] %>",,,,
eos
# Generate output
$stderr.puts("Generating output for question #{index}...")
output = template.result(binding)
# Run through the prof's question validator, if it is installed.
if validator?
$stderr.puts("Running question #{index} through official validator...")
o = `echo "#{escape(output)}" | question-validator 2>&1`
$stderr.print(o)
throw "Question #{index} did not pass official validator" unless $? == 0 && o == ''
end
# Save out the d2l formatted question if everything worked!
$stderr.puts("Question #{index} successfully generated!")
outputs.push(output)
end
$stderr.puts("\nCreating tmp dir...")
Dir.mktmpdir("se350") do |tmpdir|
dirname = 'questions'
dir = File.join(tmpdir, dirname)
Dir.mkdir(dir)
# Write each d2l question into its own file
outputs.each_with_index do |output, index|
$stderr.puts("Writing question #{index} to disk...")
File.open(File.join(dir, "#{index}.csv"), "w") do |file|
file << output
end
end
# Tar the tmpdir together
$stderr.puts("Taring all files together...")
$stdout.print `tar -C #{tmpdir} -cz #{dirname}`
$stderr.puts("Done!")
end