teuton 2.3.11 → 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -13
- data/docs/CHANGELOG.md +0 -13
- data/docs/changelog/todo.md +26 -0
- data/docs/changelog/v2.4.md +6 -2
- data/docs/dsl/execution/export.md +11 -16
- data/docs/dsl/execution/show.md +22 -7
- data/docs/ideas/{ideas.md → todo.md} +8 -16
- data/docs/install/README.md +26 -42
- data/docs/install/s-node.md +35 -0
- data/docs/install/t-node.md +76 -0
- data/docs/learn/01-target.md +34 -66
- data/docs/learn/02-config.md +35 -56
- data/docs/learn/03-remote_hosts.md +20 -1
- data/docs/learn/04-new_test.md +4 -4
- data/docs/learn/05-use.md +3 -4
- data/docs/learn/06-debug.md +6 -9
- data/docs/learn/07-log.md +14 -14
- data/docs/learn/08-readme.md +4 -4
- data/docs/learn/09-preserve.md +1 -1
- data/docs/learn/13-include.md +13 -6
- data/docs/learn/14-alias.md +14 -8
- data/docs/learn/17-hide-feedback.md +52 -0
- data/docs/learn/README.md +8 -15
- data/lib/teuton/case_manager/case/case.rb +2 -5
- data/lib/teuton/case_manager/case/dsl/expect.rb +2 -4
- data/lib/teuton/case_manager/case/dsl/log.rb +1 -2
- data/lib/teuton/case_manager/case/dsl/send.rb +4 -2
- data/lib/teuton/case_manager/case/play.rb +1 -2
- data/lib/teuton/case_manager/case/runner.rb +6 -7
- data/lib/teuton/case_manager/case_manager.rb +18 -12
- data/lib/teuton/case_manager/check_cases.rb +5 -7
- data/lib/teuton/case_manager/dsl.rb +1 -1
- data/lib/teuton/case_manager/export_manager.rb +13 -15
- data/lib/teuton/case_manager/hall_of_fame.rb +20 -16
- data/lib/teuton/case_manager/main.rb +1 -2
- data/lib/teuton/case_manager/report.rb +3 -3
- data/lib/teuton/report/formatter/base_formatter.rb +8 -7
- data/lib/teuton/report/formatter/{array_formatter.rb → default/array.rb} +44 -9
- data/lib/teuton/report/formatter/default/colored_text.rb +7 -0
- data/lib/teuton/report/formatter/default/html.rb +24 -0
- data/lib/teuton/report/formatter/default/json.rb +15 -0
- data/lib/teuton/report/formatter/{txt_formatter.rb → default/txt.rb} +4 -3
- data/lib/teuton/report/formatter/{xml_formatter.rb → default/xml.rb} +10 -4
- data/lib/teuton/report/formatter/default/yaml.rb +15 -0
- data/lib/teuton/report/formatter/formatter.rb +55 -0
- data/lib/teuton/report/formatter/moodle_csv_formatter.rb +4 -10
- data/lib/teuton/report/formatter/{resume_array_formatter.rb → resume/array.rb} +4 -7
- data/lib/teuton/report/formatter/resume/colored_text.rb +7 -0
- data/lib/teuton/report/formatter/{resume_html_formatter.rb → resume/html.rb} +7 -9
- data/lib/teuton/report/formatter/{resume_json_formatter.rb → resume/json.rb} +4 -4
- data/lib/teuton/report/formatter/{resume_txt_formatter.rb → resume/txt.rb} +4 -6
- data/lib/teuton/report/formatter/{resume_yaml_formatter.rb → resume/yaml.rb} +4 -3
- data/lib/teuton/report/report.rb +60 -43
- data/lib/teuton/report/show.rb +38 -24
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +2 -1
- metadata +38 -35
- data/docs/install/scripts.md +0 -96
- data/lib/teuton/case_manager/show.rb +0 -24
- data/lib/teuton/report/close.rb +0 -38
- data/lib/teuton/report/formatter/csv_formatter.rb +0 -25
- data/lib/teuton/report/formatter/formatter_factory.rb +0 -79
- data/lib/teuton/report/formatter/html_formatter.rb +0 -57
- data/lib/teuton/report/formatter/json_formatter.rb +0 -12
- data/lib/teuton/report/formatter/list_formatter.rb +0 -65
- data/lib/teuton/report/formatter/resume_list_formatter.rb +0 -62
- data/lib/teuton/report/formatter/yaml_formatter.rb +0 -15
@@ -9,10 +9,9 @@
|
|
9
9
|
class Case
|
10
10
|
def play
|
11
11
|
if skip?
|
12
|
-
verbose "
|
12
|
+
verbose Rainbow("S").green
|
13
13
|
return false
|
14
14
|
end
|
15
|
-
# TODO: Delete old reports???
|
16
15
|
start_time = Time.now
|
17
16
|
if get(:tt_sequence) == true
|
18
17
|
play_in_sequence
|
@@ -11,11 +11,14 @@ class Case
|
|
11
11
|
ip = @config.get("#{host}_ip".to_sym)
|
12
12
|
|
13
13
|
if protocol.to_s.downcase == "local" || host.to_s == "localhost"
|
14
|
-
|
14
|
+
# Protocol force => local
|
15
|
+
run_cmd_localhost
|
15
16
|
elsif protocol.to_s.downcase == "ssh"
|
16
|
-
|
17
|
+
# Protocol force => ssh
|
18
|
+
run_cmd_remote_ssh(host)
|
17
19
|
elsif protocol.to_s.downcase == "telnet"
|
18
|
-
|
20
|
+
# Protocol force => telnet
|
21
|
+
run_cmd_remote_telnet(host)
|
19
22
|
elsif ip.to_s.downcase == "localhost" || ip.to_s.include?("127.0.0.")
|
20
23
|
run_cmd_localhost
|
21
24
|
elsif ip == "NODATA"
|
@@ -101,17 +104,14 @@ class Case
|
|
101
104
|
rescue Errno::EHOSTUNREACH
|
102
105
|
@sessions[hostname] = :nosession
|
103
106
|
@conn_status[hostname] = :host_unreachable
|
104
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
105
107
|
log("Host #{ip} unreachable!", :error)
|
106
108
|
rescue Net::SSH::AuthenticationFailed
|
107
109
|
@sessions[hostname] = :nosession
|
108
110
|
@conn_status[hostname] = :error_authentication_failed
|
109
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
110
111
|
log("SSH::AuthenticationFailed!", :error)
|
111
112
|
rescue Net::SSH::HostKeyMismatch
|
112
113
|
@sessions[hostname] = :nosession
|
113
114
|
@conn_status[hostname] = :host_key_mismatch
|
114
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
115
115
|
log("SSH::HostKeyMismatch!", :error)
|
116
116
|
log("* The destination server's fingerprint is not matching " \
|
117
117
|
"what is in your local known_hosts file.", :error)
|
@@ -121,7 +121,6 @@ class Case
|
|
121
121
|
rescue => e
|
122
122
|
@sessions[hostname] = :nosession
|
123
123
|
@conn_status[hostname] = :error
|
124
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
125
124
|
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
126
125
|
" exec: #{@action[:command]}", :error)
|
127
126
|
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "rainbow"
|
3
2
|
require "singleton"
|
4
3
|
require_relative "../application"
|
5
4
|
require_relative "../report/report"
|
5
|
+
require_relative "../report/show"
|
6
6
|
require_relative "../utils/configfile_reader"
|
7
7
|
require_relative "case/case"
|
8
8
|
require_relative "export_manager"
|
9
9
|
require_relative "main"
|
10
|
-
require_relative "utils"
|
11
10
|
|
12
11
|
# This class does all the job
|
13
12
|
# Organize the hole job, sending orders to others classes
|
@@ -18,13 +17,11 @@ require_relative "utils"
|
|
18
17
|
# * case_manager/export
|
19
18
|
# * case_manager/hall_of_fame
|
20
19
|
# * case_manager/report
|
21
|
-
# * case_manager/show
|
22
20
|
class CaseManager
|
23
21
|
include Singleton
|
24
22
|
include Utils
|
23
|
+
attr_reader :report, :cases
|
25
24
|
|
26
|
-
##
|
27
|
-
# Initialize CaseManager
|
28
25
|
def initialize
|
29
26
|
@cases = []
|
30
27
|
@report = Report.new(0)
|
@@ -50,12 +47,13 @@ class CaseManager
|
|
50
47
|
# @param args (Hash) Export options
|
51
48
|
def export(args = {})
|
52
49
|
if args.class != Hash
|
53
|
-
puts "[ERROR]
|
54
|
-
|
55
|
-
puts "
|
56
|
-
|
50
|
+
puts Rainbow("[ERROR] Argument error with 'export'!").red
|
51
|
+
puts Rainbow(" Code : CaseManager#export").red
|
52
|
+
puts Rainbow(" Line : export #{args}").red
|
53
|
+
puts Rainbow(" Use : export format: 'txt'").red
|
54
|
+
puts ""
|
55
|
+
exit 1
|
57
56
|
end
|
58
|
-
# Export report files
|
59
57
|
ExportManager.run(@report, @cases, args)
|
60
58
|
end
|
61
59
|
|
@@ -65,8 +63,16 @@ class CaseManager
|
|
65
63
|
def send(args = {})
|
66
64
|
threads = []
|
67
65
|
puts ""
|
68
|
-
puts "
|
66
|
+
puts Rainbow("-" * 50).green
|
67
|
+
puts Rainbow("Sending files...#{args}").color(:green)
|
69
68
|
@cases.each { |c| threads << Thread.new { c.send(args) } }
|
70
69
|
threads.each(&:join)
|
70
|
+
puts Rainbow("Sending finished!").color(:green)
|
71
|
+
puts Rainbow("-" * 50).green
|
72
|
+
end
|
73
|
+
|
74
|
+
def show(options = {verbose: 1})
|
75
|
+
verbose = options[:verbose]
|
76
|
+
ShowReport.new(@report).call(verbose)
|
71
77
|
end
|
72
78
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "hall_of_fame"
|
2
2
|
|
3
3
|
class CaseManager
|
4
4
|
private
|
@@ -32,18 +32,16 @@ class CaseManager
|
|
32
32
|
close_main_report(start_time)
|
33
33
|
end
|
34
34
|
|
35
|
-
##
|
36
|
-
# Run all cases
|
37
35
|
def run_all_cases
|
38
36
|
start_time = Time.now
|
37
|
+
verboseln Rainbow("-" * 36).green
|
38
|
+
verboseln Rainbow("Started at #{start_time}").green
|
39
39
|
if Application.instance.global[:tt_sequence] == true
|
40
|
-
verboseln Rainbow("==> Teuton: Running in sequence (#{start_time})").yellow.bright
|
41
40
|
# Run every case in sequence
|
42
41
|
@cases.each(&:play)
|
43
42
|
else
|
44
|
-
verboseln Rainbow("==> Teuton: Running in parallel (#{start_time})").yellow.bright
|
45
|
-
threads = []
|
46
43
|
# Run all cases in parallel
|
44
|
+
threads = []
|
47
45
|
@cases.each { |c| threads << Thread.new { c.play } }
|
48
46
|
threads.each(&:join)
|
49
47
|
end
|
@@ -75,6 +73,6 @@ class CaseManager
|
|
75
73
|
@cases.each { |c| threads << Thread.new { c.close uniques } }
|
76
74
|
threads.each(&:join)
|
77
75
|
|
78
|
-
|
76
|
+
HallOfFame.new(@cases).call
|
79
77
|
end
|
80
78
|
end
|
@@ -8,22 +8,22 @@ module ExportManager
|
|
8
8
|
# @param main_report (Report)
|
9
9
|
# @param cases (Array)
|
10
10
|
# @param input (Hash) Selected export options
|
11
|
-
def self.run(main_report, cases,
|
12
|
-
|
11
|
+
def self.run(main_report, cases, args)
|
12
|
+
options = strings2symbols(args)
|
13
|
+
if options[:format].nil?
|
14
|
+
options[:format] = Application.instance.default[:format]
|
15
|
+
end
|
13
16
|
|
14
|
-
# default :mode=>:all, :format=>:txt
|
15
|
-
format = args[:format] || Application.instance.default[:format]
|
16
|
-
mode = args[:mode] || :all
|
17
17
|
# Step 1: Export case reports
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
18
|
+
threads = []
|
19
|
+
cases.each { |c| threads << Thread.new { c.export(options) } }
|
20
|
+
threads.each(&:join)
|
21
|
+
|
23
22
|
# Step 2: Export resume report
|
24
|
-
main_report.export_resume
|
23
|
+
main_report.export_resume(options)
|
24
|
+
|
25
25
|
# Step 3: Preserve files if required
|
26
|
-
preserve_files if
|
26
|
+
preserve_files if options[:preserve] == true
|
27
27
|
end
|
28
28
|
|
29
29
|
##
|
@@ -42,7 +42,7 @@ module ExportManager
|
|
42
42
|
end
|
43
43
|
|
44
44
|
##
|
45
|
-
# Preserve output files for current project
|
45
|
+
# Preserve output files for current project execution
|
46
46
|
private_class_method def self.preserve_files
|
47
47
|
app = Application.instance
|
48
48
|
t = Time.now
|
@@ -55,6 +55,4 @@ module ExportManager
|
|
55
55
|
FileUtils.mkdir(logdir)
|
56
56
|
Dir.glob(File.join(srcdir, "**.*")).each { |file| FileUtils.cp(file, logdir) }
|
57
57
|
end
|
58
|
-
# rubocop:enable Metrics/AbcSize
|
59
|
-
# rubocop:enable Metrics/MethodLength
|
60
58
|
end
|
@@ -1,26 +1,30 @@
|
|
1
1
|
require_relative "../application"
|
2
2
|
|
3
3
|
class CaseManager
|
4
|
-
|
4
|
+
class HallOfFame
|
5
|
+
def initialize(cases)
|
6
|
+
@cases = cases
|
7
|
+
end
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
def call
|
10
|
+
celebrities = {}
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
@cases.each do |c|
|
13
|
+
grade = c.grade # report.tail[:grade]
|
14
|
+
label = if celebrities[grade]
|
15
|
+
celebrities[grade] + "*"
|
16
|
+
else
|
17
|
+
"*"
|
18
|
+
end
|
19
|
+
celebrities[grade] = label unless c.skip
|
15
20
|
end
|
16
|
-
celebrities[grade] = label unless c.skip
|
17
|
-
end
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
a = celebrities.sort_by { |key, _value| key }
|
23
|
+
list = a.reverse
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
app = Application.instance
|
26
|
+
app.options[:case_number] = @cases.size
|
27
|
+
app.hall_of_fame = list
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
@@ -25,8 +25,8 @@ class CaseManager
|
|
25
25
|
@report.tail[:duration] = finish_time - start_time
|
26
26
|
|
27
27
|
duration = format("%3.3f", (finish_time - start_time))
|
28
|
-
|
29
|
-
verboseln Rainbow("
|
28
|
+
verboseln Rainbow("\nFinished in #{duration} seconds").green
|
29
|
+
verboseln Rainbow("-" * 36).green
|
30
30
|
verboseln " "
|
31
31
|
|
32
32
|
app = Application.instance
|
@@ -37,7 +37,7 @@ class CaseManager
|
|
37
37
|
skip: true,
|
38
38
|
id: "-",
|
39
39
|
grade: 0.0,
|
40
|
-
letter: "",
|
40
|
+
letter: "S",
|
41
41
|
members: "-",
|
42
42
|
conn_status: {},
|
43
43
|
moodle_id: "",
|
@@ -1,18 +1,19 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
class BaseFormatter
|
2
|
+
attr_reader :ext
|
3
|
+
|
4
4
|
def initialize(report)
|
5
|
-
@head = report.head
|
6
|
-
@lines = report.lines
|
7
|
-
@tail = report.tail
|
5
|
+
@head = report.head.clone
|
6
|
+
@lines = report.lines.clone
|
7
|
+
@tail = report.tail.clone
|
8
|
+
@ext = "unkown"
|
8
9
|
end
|
9
10
|
|
10
|
-
def process
|
11
|
+
def process(options = {})
|
11
12
|
raise "Empty method!"
|
12
13
|
end
|
13
14
|
|
14
15
|
def init(filename)
|
15
|
-
@filename = filename
|
16
|
+
@filename = "#{filename}.#{@ext}"
|
16
17
|
@file = File.open(@filename, "w")
|
17
18
|
end
|
18
19
|
|
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative "base_formatter"
|
1
|
+
require_relative "../base_formatter"
|
2
|
+
require_relative "../../../application"
|
4
3
|
|
5
4
|
class ArrayFormatter < BaseFormatter
|
6
5
|
def initialize(report)
|
@@ -8,26 +7,28 @@ class ArrayFormatter < BaseFormatter
|
|
8
7
|
@data = {}
|
9
8
|
end
|
10
9
|
|
11
|
-
def process
|
12
|
-
build_data
|
10
|
+
def process(options = {})
|
11
|
+
build_data(options)
|
13
12
|
w @data.to_s # Write data into ouput file
|
14
13
|
deinit
|
15
14
|
end
|
16
15
|
|
17
|
-
def build_data
|
16
|
+
def build_data(options)
|
18
17
|
build_initial_data
|
19
|
-
build_history_data
|
18
|
+
build_history_data(options)
|
20
19
|
build_final_data
|
21
20
|
build_hof_data
|
22
21
|
end
|
23
22
|
|
23
|
+
private
|
24
|
+
|
24
25
|
def build_initial_data
|
25
26
|
head = {}
|
26
27
|
@head.each { |key, value| head[key] = value }
|
27
28
|
@data[:config] = head
|
28
29
|
end
|
29
30
|
|
30
|
-
def build_history_data
|
31
|
+
def build_history_data(options)
|
31
32
|
@data[:logs] = []
|
32
33
|
groups = []
|
33
34
|
title = nil
|
@@ -54,12 +55,22 @@ class ArrayFormatter < BaseFormatter
|
|
54
55
|
target[:score] = value
|
55
56
|
target[:weight] = i[:weight]
|
56
57
|
target[:description] = i[:description]
|
57
|
-
|
58
|
+
|
58
59
|
target[:conn_type] = i[:conn_type]
|
59
60
|
target[:duration] = i[:duration]
|
61
|
+
|
62
|
+
target[:command] = i[:command]
|
60
63
|
target[:alterations] = i[:alterations]
|
61
64
|
target[:expected] = i[:expected]
|
62
65
|
target[:result] = i[:result]
|
66
|
+
|
67
|
+
if options[:feedback] == false
|
68
|
+
target[:command] = "*" * i[:command].size
|
69
|
+
target[:alterations] = "*" * i[:alterations].size
|
70
|
+
target[:expected] = "*" * i[:expected].size
|
71
|
+
target[:result] = "*" * i[:result].size
|
72
|
+
end
|
73
|
+
|
63
74
|
targets << target
|
64
75
|
end
|
65
76
|
|
@@ -82,4 +93,28 @@ class ArrayFormatter < BaseFormatter
|
|
82
93
|
app.hall_of_fame.each { |line| fame[line[0]] = line[1] }
|
83
94
|
@data[:hall_of_fame] = fame
|
84
95
|
end
|
96
|
+
|
97
|
+
def config
|
98
|
+
@data[:config]
|
99
|
+
end
|
100
|
+
|
101
|
+
def results
|
102
|
+
@data[:results]
|
103
|
+
end
|
104
|
+
|
105
|
+
def logs
|
106
|
+
@data[:logs]
|
107
|
+
end
|
108
|
+
|
109
|
+
def groups
|
110
|
+
@data[:groups]
|
111
|
+
end
|
112
|
+
|
113
|
+
def hall_of_fame
|
114
|
+
@data[:hall_of_fame]
|
115
|
+
end
|
116
|
+
|
117
|
+
def version
|
118
|
+
Application::VERSION
|
119
|
+
end
|
85
120
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "erb"
|
2
|
+
require_relative "yaml"
|
3
|
+
|
4
|
+
class HTMLFormatter < YAMLFormatter
|
5
|
+
def initialize(report)
|
6
|
+
super(report)
|
7
|
+
@ext = "html"
|
8
|
+
@data = {}
|
9
|
+
basedir = File.join(File.dirname(__FILE__), "..", "..", "..")
|
10
|
+
filepath = File.join(basedir, "files", "template", "case.html")
|
11
|
+
@template = File.read(filepath)
|
12
|
+
end
|
13
|
+
|
14
|
+
def process(options = {})
|
15
|
+
build_data(options)
|
16
|
+
build_page
|
17
|
+
deinit
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_page
|
21
|
+
render = ERB.new(@template)
|
22
|
+
w render.result(binding)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "json/pure"
|
2
|
+
require_relative "array"
|
3
|
+
|
4
|
+
class JSONFormatter < ArrayFormatter
|
5
|
+
def initialize(report)
|
6
|
+
super(report)
|
7
|
+
@ext = "json"
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(options = {})
|
11
|
+
build_data(options)
|
12
|
+
w @data.to_json # Write data into ouput file
|
13
|
+
deinit
|
14
|
+
end
|
15
|
+
end
|
@@ -1,19 +1,20 @@
|
|
1
1
|
require "terminal-table"
|
2
2
|
require "rainbow"
|
3
|
-
require_relative "
|
3
|
+
require_relative "array"
|
4
4
|
|
5
5
|
class TXTFormatter < ArrayFormatter
|
6
6
|
def initialize(report, color = false)
|
7
7
|
@color = color
|
8
8
|
super(report)
|
9
|
+
@ext = "txt"
|
9
10
|
@data = {}
|
10
11
|
end
|
11
12
|
|
12
|
-
def process
|
13
|
+
def process(options = {})
|
13
14
|
rainbow_state = Rainbow.enabled
|
14
15
|
Rainbow.enabled = @color
|
15
16
|
|
16
|
-
build_data
|
17
|
+
build_data(options)
|
17
18
|
process_config
|
18
19
|
process_logs
|
19
20
|
process_groups
|
@@ -1,9 +1,15 @@
|
|
1
|
-
require_relative "base_formatter"
|
1
|
+
require_relative "../base_formatter"
|
2
|
+
require_relative "../../../version"
|
2
3
|
|
3
4
|
class XMLFormatter < BaseFormatter
|
4
|
-
def
|
5
|
+
def initialize(report)
|
6
|
+
super(report)
|
7
|
+
@ext = "xml"
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(options = {})
|
5
11
|
tab = " "
|
6
|
-
w "<teuton version='
|
12
|
+
w "<teuton version='#{Teuton::VERSION}'>\n"
|
7
13
|
w "#{tab}<head>\n"
|
8
14
|
@head.each { |key, value| w "#{tab * 2}<#{key}>#{value}</#{key}>\n" }
|
9
15
|
w "#{tab}</head>\n"
|
@@ -22,7 +28,7 @@ class XMLFormatter < BaseFormatter
|
|
22
28
|
w "#{tab * 3}<check>#{i[:check]}</check>\n"
|
23
29
|
w "#{tab * 3}<weigth>#{i[:weight]}</weigth>\n"
|
24
30
|
w "#{tab * 2}</line>\n"
|
25
|
-
|
31
|
+
end
|
26
32
|
w "#{tab}</lines>\n"
|
27
33
|
w "#{tab}<tail>\n"
|
28
34
|
@tail.each { |key, value| w "#{tab * 2}<#{key}>#{value}</#{key}>\n" }
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require_relative "array"
|
3
|
+
|
4
|
+
class YAMLFormatter < ArrayFormatter
|
5
|
+
def initialize(report)
|
6
|
+
super(report)
|
7
|
+
@ext = "yaml"
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(options = {})
|
11
|
+
build_data(options)
|
12
|
+
w @data.to_yaml # Write data into ouput file
|
13
|
+
deinit
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "rainbow"
|
2
|
+
require_relative "default/colored_text"
|
3
|
+
require_relative "default/html"
|
4
|
+
require_relative "default/json"
|
5
|
+
require_relative "default/txt"
|
6
|
+
require_relative "default/xml"
|
7
|
+
require_relative "default/yaml"
|
8
|
+
require_relative "resume/colored_text"
|
9
|
+
require_relative "resume/html"
|
10
|
+
require_relative "resume/json"
|
11
|
+
require_relative "resume/txt"
|
12
|
+
require_relative "resume/yaml"
|
13
|
+
require_relative "moodle_csv_formatter"
|
14
|
+
|
15
|
+
module Formatter
|
16
|
+
def self.call(report, options, filename)
|
17
|
+
klass = get(options[:format])
|
18
|
+
if klass.nil?
|
19
|
+
puts Rainbow("[ERROR] Unkown format: #{options[:format]}").red
|
20
|
+
puts Rainbow(" export format: FORMAT").red
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
formatter = klass.new(report)
|
24
|
+
formatter.init(filename)
|
25
|
+
report.format = formatter.ext
|
26
|
+
formatter.process(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.get(format)
|
30
|
+
list = {
|
31
|
+
colored_text: ColoredTextFormatter,
|
32
|
+
html: HTMLFormatter,
|
33
|
+
json: JSONFormatter,
|
34
|
+
txt: TXTFormatter,
|
35
|
+
xml: XMLFormatter,
|
36
|
+
yaml: YAMLFormatter,
|
37
|
+
moodle_csv: MoodleCSVFormatter,
|
38
|
+
resume_html: ResumeHTMLFormatter,
|
39
|
+
resume_json: ResumeJSONFormatter,
|
40
|
+
resume_txt: ResumeTXTFormatter,
|
41
|
+
resume_xml: ResumeTXTFormatter, # TODO
|
42
|
+
resume_yaml: ResumeYAMLFormatter
|
43
|
+
}
|
44
|
+
list[format]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.hide_feedback(report)
|
48
|
+
report2 = report.clone
|
49
|
+
report2.groups.each do |group|
|
50
|
+
group.each do |item|
|
51
|
+
puts item.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,20 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative "resume_array_formatter"
|
1
|
+
require_relative "resume/array"
|
4
2
|
|
5
3
|
class MoodleCSVFormatter < ResumeArrayFormatter
|
6
|
-
##
|
7
|
-
# initialize instance
|
8
|
-
# @param report (Report)
|
9
4
|
def initialize(report)
|
10
5
|
super(report)
|
6
|
+
@ext = "csv"
|
11
7
|
@data = {}
|
12
8
|
end
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
def process
|
17
|
-
build_data
|
10
|
+
def process(options = {})
|
11
|
+
build_data(options)
|
18
12
|
process_cases
|
19
13
|
deinit
|
20
14
|
end
|
@@ -1,21 +1,18 @@
|
|
1
|
-
|
1
|
+
require_relative "../base_formatter"
|
2
2
|
|
3
|
-
require_relative "base_formatter"
|
4
|
-
|
5
|
-
# ArrayFormatter class: format report data into an array
|
6
3
|
class ResumeArrayFormatter < BaseFormatter
|
7
4
|
def initialize(report)
|
8
5
|
super(report)
|
9
6
|
@data = {}
|
10
7
|
end
|
11
8
|
|
12
|
-
def process
|
13
|
-
build_data
|
9
|
+
def process(options = {})
|
10
|
+
build_data(options)
|
14
11
|
w @data.to_s # Write data into ouput file
|
15
12
|
deinit
|
16
13
|
end
|
17
14
|
|
18
|
-
def build_data
|
15
|
+
def build_data(options)
|
19
16
|
build_initial_data
|
20
17
|
build_cases_data
|
21
18
|
build_final_data
|