Module: Ziuma

Defined in:
lib/ziuma.rb

Overview

Main module

Class Method Summary collapse

Class Method Details

.catch_no_init(filename) ⇒ Object

Catches a lack of initialization



39
40
41
42
43
# File 'lib/ziuma.rb', line 39

def self.catch_no_init(filename)
  yield
rescue Errno::ENOENT
  abort format NO_INIT_MESSAGE, filename
end

.choose_copy(filename, destination) ⇒ Object

Lets the user choose to replace or not existing files



17
18
19
20
21
22
23
24
25
26
# File 'lib/ziuma.rb', line 17

def self.choose_copy(filename, destination)
  if File.exist? filename
    print "#{filename} already exists. Do you want to replace it? (y/N) "
    if $stdin.gets.chomp.upcase == 'Y'
      FileUtils.cp File.join(destination, filename), '.'
    end
  else
    FileUtils.cp File.join(destination, filename), '.'
  end
end

.generate!Object

Generates a quiz from the quiz.yaml and quiz.tex.yaml file in the working directory



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
# File 'lib/ziuma.rb', line 63

def self.generate!
  require 'erb'
  require 'securerandom'

  id = SecureRandom.hex 2
  contents =
    catch_no_init(YAML_FILENAME) do
      YAML.load_file YAML_FILENAME, symbolize_names: true
    end
  title = contents[:title]
  instructions = contents[:instructions]
  questions =
    contents[:questions].shuffle.map do |e|
      {
        question: e[:question],
        checkboxes: e[:checkboxes],
        choices: (e[:ordered] ? e[:choices] : e[:choices].shuffle)
      }
    end
  tex =
    catch_no_init(TEX_FILENAME) do
      ERB.new File.read(TEX_FILENAME), trim_mode: '-'
    end
  filename = "#{id}.tex"
  File.write filename, tex.result(binding)
  puts filename
end

.initObject

Copies the templates in the working directory



29
30
31
32
33
34
35
36
# File 'lib/ziuma.rb', line 29

def self.init
  require 'fileutils'

  template_dir = File.expand_path('templates', __dir__)
  [YAML_FILENAME, TEX_FILENAME].each do |e|
    choose_copy e, template_dir
  end
end

.parse(args) ⇒ Object

Parses the command line



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/ziuma.rb', line 92

def self.parse(args)
  program = File.basename $PROGRAM_NAME
  case args
  in ['init' | 'i']
    init
  in ['validate' | 'v']
    validate
  in ['generate' | 'g', n]
    Integer(n, 10).times { generate! }
  in ['help' | 'h', *rest]
    case rest
    in ['init' | 'i']
      puts "Usage: #{program} init"
      puts 'Generates quiz.yaml and quiz.tex.erb in the working directory.'
    in ['validate' | 'v']
      puts "Usage: #{program} validate"
      puts 'Validates the quiz.yaml file in the working directory against the ziuma JSON schema.'
    in ['generate' | 'g']
      puts "Usage: #{program} generate N"
      puts <<~MSG.gsub "\n", ' '
        Generates N quizzes based on the quiz.yaml
        and quiz.tex.erb files in the working directory.
      MSG
    else
      puts "Usage: #{program} help (init | validate | generate)"
    end
  else
    puts "Usage: #{program} (help <command> | init | validate | generate N)"
  end
end

.validateObject

Validates a quiz.yaml file against the JSON schema



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ziuma.rb', line 46

def self.validate
  require 'json-schema'

  schema_dir = File.expand_path 'schemas', __dir__
  schema = JSON.load_file File.join schema_dir, 'schema.json'
  contents = catch_no_init(YAML_FILENAME) { YAML.load_file YAML_FILENAME }
  case JSON::Validator.fully_validate schema, contents
  in []
    puts 'Validation successful!'
  in errors
    errors.each { puts _1 }
    exit 1
  end
end