reviser 0.0.2.rc1 → 0.0.2

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +143 -10
  4. data/bin/reviser +1 -1
  5. data/config.yml +1 -6
  6. data/ext/valgrind.rb +7 -3
  7. data/ext/web_validators.rb +44 -80
  8. data/lang/HTML.yml +5 -0
  9. data/lib/exec.rb +36 -24
  10. data/lib/{component.rb → reviser/component.rb} +17 -3
  11. data/lib/{components → reviser/components}/archiver.rb +4 -8
  12. data/lib/{components → reviser/components}/checker.rb +6 -3
  13. data/lib/{components → reviser/components}/extractors.rb +1 -1
  14. data/lib/{components → reviser/components}/generator.rb +16 -8
  15. data/lib/{components → reviser/components}/generators.rb +14 -37
  16. data/lib/{components → reviser/components}/organiser.rb +0 -0
  17. data/lib/reviser/config.rb +104 -0
  18. data/lib/{criteria → reviser/criteria}/code_analysis.rb +0 -0
  19. data/lib/{criteria → reviser/criteria}/compilation.rb +14 -7
  20. data/lib/{criteria → reviser/criteria}/execution.rb +13 -13
  21. data/lib/{helpers → reviser/helpers}/criteria.rb +6 -3
  22. data/lib/{helpers → reviser/helpers}/git.rb +0 -0
  23. data/lib/{helpers → reviser/helpers}/project.rb +17 -12
  24. data/lib/{helpers → reviser/helpers}/system.rb +0 -0
  25. data/lib/{loggers → reviser/loggers}/logger.rb +1 -2
  26. data/lib/{loggers → reviser/loggers}/modes.rb +1 -1
  27. data/lib/reviser/result.rb +30 -0
  28. data/lib/reviser.rb +15 -15
  29. data/res/css/component.css +3 -1
  30. data/res/example/data.json +4 -0
  31. data/type/{CProject.yml → example/CProject.yml} +0 -0
  32. data/type/{HelloWorldRuby.yml → example/HelloWorldRuby.yml} +0 -0
  33. data/type/{HtmlASRALL.yml → example/HtmlASRALL.yml} +0 -0
  34. data/type/{JavaProject.yml → example/JavaProject.yml} +0 -0
  35. data/type/{Labyrinthe.yml → example/Labyrinthe.yml} +0 -0
  36. data/type/{Pendu.yml → example/Pendu.yml} +0 -0
  37. data/type/{Web.yml → example/Web.yml} +0 -0
  38. metadata +37 -43
  39. data/lib/config.rb +0 -66
  40. data/res/js/jquery.stickyheader.js +0 -149
@@ -1,5 +1,7 @@
1
1
  require_relative 'generators'
2
2
 
3
+ require_relative '../result'
4
+
3
5
  module Reviser
4
6
  module Components
5
7
 
@@ -20,15 +22,21 @@ module Reviser
20
22
 
21
23
  # Runs the generation of results file in all asked formats by user.
22
24
  def run
23
- begin
24
- if Cfg[:out_format].respond_to? 'each'
25
- Cfg[:out_format].each { |f| send f.to_sym }
26
- else
27
- send Cfg[:out_format].to_sym
25
+ #begin
26
+ Cfg[:out_format].each do |format|
27
+ # Deep copy !!!
28
+ arg = Marshal.load(Marshal.dump(@data))
29
+ arg.each do |project, results|
30
+ results.each do |criterion, value|
31
+ arg[project][criterion] = value.send(format.to_sym).to_s.encode! 'utf-8', :invalid => :replace
32
+ end
33
+ end
34
+
35
+ send format.to_sym, arg
28
36
  end
29
- rescue Object => e
30
- @logger.h1 Logger::FATAL, "Wrong format : #{e.to_s}"
31
- end
37
+ #rescue Object => e
38
+ # @logger.h1 Logger::FATAL, "Wrong format : #{e.to_s}"
39
+ #end
32
40
  end
33
41
 
34
42
  # Gets all criterias of marking
@@ -35,21 +35,21 @@ module Reviser
35
35
  module Generators
36
36
 
37
37
  # Generates the CSV file
38
- def csv(ext = '.csv')
38
+ def csv data, ext = '.csv'
39
39
  require 'csv'
40
40
  CSV.open(out(ext), 'wb') do |f|
41
41
  # Criterias as columns
42
42
  f << (criterias).unshift('projet')
43
43
 
44
44
  # Values for each project as rows
45
- @data.keys.each do |proj|
46
- f << @data[proj].values.unshift(proj)
45
+ data.keys.each do |proj|
46
+ f << data[proj].values.unshift(proj)
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
51
  # Generates a Excel file
52
- def xls(ext = '.xls')
52
+ def xls data, ext = '.xls'
53
53
  require 'spreadsheet'
54
54
  Spreadsheet.client_encoding = 'UTF-8'
55
55
  book = Spreadsheet::Workbook.new
@@ -67,51 +67,35 @@ module Reviser
67
67
  sheet.row(0).height = 18
68
68
 
69
69
  # Values for each project as rows
70
- @data.keys.each_with_index do |proj, i|
71
- sheet.insert_row(i+1,@data[proj].values.unshift(proj))
70
+ data.keys.each_with_index do |proj, i|
71
+ sheet.insert_row(i+1, data[proj].values.unshift(proj))
72
72
  end
73
73
 
74
74
  book.write out(ext)
75
75
  end
76
76
 
77
77
  # Generates an HTML file
78
- def html(ext = '.html')
78
+ def html data, ext = '.html'
79
79
  out = '<!DOCTYPE html><html><head>'
80
80
  out += '<meta charset= "UTF-8">'
81
- out += "<link rel=\"stylesheet\" href=\"#{Cfg[:res_dir]}/css/component.css\" />"
82
- out += "<link rel=\"stylesheet\" href=\"#{Cfg[:res_dir]}/css/normalize.css\" />"
83
- out += '<script src="res/js/component.css"></script>'
81
+ out += "<link rel=\"stylesheet\" href=\"#{Cfg.resource('/css/component.css').to_path}\" />"
82
+ out += "<link rel=\"stylesheet\" href=\"#{Cfg.resource('/css/normalize.css').to_path}\" />"
84
83
  out += '<title>Results</title>'
85
- out += "</head>\n<body><table><thead>"
86
- out += ' <tr>'
84
+ out += "</head>\n<body><table><thead><tr>"
87
85
 
88
86
  criterias.unshift('Projet').each { |crit| out += "<th>#{crit}</th>" }
89
87
 
90
88
  out += '</tr></thead><tbody>'
91
89
  # Values for each project as rows
92
- @data.keys.each do |proj|
90
+ data.keys.each do |proj|
93
91
  out += "<tr><th>#{proj}</th>"
94
- @data[proj].each do |k, v|
95
- if k.to_s[/(compilation|execution)/]
96
- out += '<td class="console">'
97
- else
98
- out += '<td>'
99
- end
100
-
101
- # If file, generate a link, else do nothing !
102
- out += file?(v) && "<pre><a href=\"#{v.gsub(' ','%20')}\" target=\"_blank\">#{v}</a></pre></td>" ||"<pre>#{v}</pre></td>"
103
-
92
+ data[proj].each do |k, v|
93
+ out += "<td><pre>#{v}</pre></td>"
104
94
  end
105
95
  out += '</tr>'
106
96
  end
107
97
 
108
- out += '</tbody></table>'
109
-
110
- out += '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>'
111
- out += '<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-throttle-debounce/1.1/jquery.ba-throttle-debounce.min.js"></script>'
112
- #out += "<script src=\"#{Cfg[:res_dir]}/js/jquery.stickyheader.js\"></script>"
113
-
114
- out += '</body></html>'
98
+ out += '</tbody></table></body></html>'
115
99
 
116
100
  File.open(out(ext), 'w') { |f| f.write(out) }
117
101
  end
@@ -122,13 +106,6 @@ module Reviser
122
106
  Cfg[:out] + ext
123
107
  end
124
108
 
125
- # Checks if result is a existing file.
126
- # @param path [String] of possible file
127
- # @return [Boolean] True if the path is a real file.
128
- def file? path
129
- File.exist? path.to_s
130
- end
131
-
132
109
  end
133
110
  end
134
111
  end
File without changes
@@ -0,0 +1,104 @@
1
+ #
2
+ # @author Renan Strauss
3
+ # Externalises the configuration
4
+ #
5
+ require 'yaml'
6
+
7
+ module Reviser
8
+ class Cfg
9
+ # Path for specialized config files for projects
10
+ ROOT = File.join(File.dirname(File.dirname(File.dirname(__FILE__))))
11
+
12
+ #
13
+ # TODO : let the user dynamically add
14
+ # his own directories
15
+ #
16
+
17
+ # Resources dir
18
+ RES_DIR = 'res'
19
+ # Project's type dir
20
+ TYPE_DIR = 'type'
21
+
22
+ # Is the config is loaded ?
23
+ @@loaded = false
24
+
25
+ def self.[](key)
26
+ @@mem[key] if @@loaded
27
+ end
28
+
29
+ def self.[]=(key, value)
30
+ @@mem[key] = value if @@loaded
31
+ end
32
+
33
+ # @return true if there is the key in the config
34
+ def self.has_key?(key)
35
+ @@mem.has_key? key
36
+ end
37
+
38
+ #
39
+ # @returns The specified resource path
40
+ # TODO : put resources in dedicated folders
41
+ # for each component or extension, so that
42
+ # the user can omit <lang>/<ext_name>/ when
43
+ # calling this method
44
+ #
45
+ def self.resource path
46
+ abs = File.join @@workspace_root, RES_DIR, path
47
+ File.new abs if File.exists? abs
48
+ end
49
+
50
+
51
+ def self.load(cfg_file)
52
+ @@mem = {}
53
+ @@workspace_root = File.dirname(cfg_file)
54
+
55
+ #
56
+ # read our main config file
57
+ #
58
+ populate YAML.load(File.read(cfg_file))
59
+
60
+ #
61
+ # look for project's type
62
+ type_file = File.join(@@workspace_root, TYPE_DIR, "#{@@mem[:type]}.yml")
63
+ begin
64
+ type_cfg = YAML.load(File.read(type_file))
65
+ rescue => e
66
+ puts "File #{type_file} not found. Aborting..."
67
+ exit
68
+ end
69
+
70
+ populate YAML.load(File.read(File.join(ROOT, 'lang', "#{type_cfg['language']}.yml")))
71
+ # So that project's type Cfg overrides
72
+ # lang Cfg
73
+ populate type_cfg
74
+
75
+ setup_defaults
76
+
77
+ @@loaded = true
78
+ end
79
+
80
+ def self.setup_defaults
81
+ #
82
+ # Default values for optional keys
83
+ #
84
+ Cfg[:options] ||= { verbose: true, log_dir:'logs', log_mode: 'org' }
85
+ Cfg[:timeout] ||= 4
86
+ Cfg[:out] ||= 'results'
87
+ Cfg[:out_format] ||= ['html', 'csv', 'xls']
88
+ Cfg[:required_files] ||= []
89
+
90
+ Cfg[:program_prefix] ||= ''
91
+ Cfg[:execution_command] ||= ''
92
+ Cfg[:execution_count] ||= 1
93
+ end
94
+
95
+ private
96
+ #
97
+ # Handy method to convert string keys
98
+ # read from Cfg file to symbols
99
+ #
100
+ def self.populate(hash)
101
+ hash.each { |k, v| @@mem[k.to_sym] = v}
102
+ end
103
+ end
104
+ end
File without changes
@@ -9,7 +9,6 @@
9
9
  module Reviser
10
10
  module Criteria
11
11
  module Compilation
12
- include Helpers::Project
13
12
  include Helpers::System
14
13
 
15
14
  #
@@ -23,18 +22,26 @@ module Reviser
23
22
  # understandable in the Cfg
24
23
  #
25
24
  if missing_files.empty?
26
- cmd = "#{Cfg[(Cfg.has_key? :preferred_build_command) && :preferred_build_command || :default_build_command]}"
25
+ result = ''
26
+
27
+ cmd = "#{Cfg[Cfg.has_key?(:preferred_build_command) && :preferred_build_command || :default_build_command]}"
27
28
  out = exec_with_timeout cmd
28
29
 
29
30
  if out.has_key? :process_status
30
- return "Exit status: 0\r#{out[:stdout]}" unless out[:process_status].exitstatus != 0
31
+ result = "Exit status: 0\r#{out[:stdout]}" unless out[:process_status].exitstatus != 0
32
+ else
33
+ if Cfg.has_key? :preferred_build_command
34
+ out = exec_with_timeout Cfg[:default_build_command]
35
+ end
31
36
  end
32
37
 
33
- if Cfg.has_key? :preferred_build_command
34
- out = exec_with_timeout Cfg[:default_build_command]
35
- end
38
+ result = "#{out[:stdout]}\r#{out[:stderr]}"
36
39
 
37
- (out[:process_status].exitstatus == 0) ? "Exit status: 0\r#{out[:stdout]}" : "#{out[:stdout]}\r#{out[:stderr]}"
40
+ manufacture do |format|
41
+ format.html { '<div class="console">' + result + '</div>' }
42
+ format.csv { result }
43
+ format.xls { result }
44
+ end
38
45
  end
39
46
  end
40
47
  end
@@ -22,29 +22,30 @@ module Reviser
22
22
  if Cfg.has_key? :execution_value
23
23
  if Cfg[:execution_value].respond_to? 'each'
24
24
  Cfg[:execution_value].each do |v|
25
- outputs << exec(v)
25
+ outputs << make_exec(v)
26
26
  end
27
27
  else
28
28
  if Cfg.has_key? :execution_count
29
29
  outputs[Cfg[:execution_value]] = []
30
30
  Cfg[:execution_count].times do
31
- outputs << exec(Cfg[:execution_value])
31
+ outputs << make_exec(Cfg[:execution_value])
32
32
  end
33
33
  else
34
- outputs << exec(Cfg[:execution_value])
34
+ outputs << make_exec(Cfg[:execution_value])
35
35
  end
36
36
  end
37
37
  else
38
- if Cfg.has_key? :execution_count
39
- Cfg[:execution_count].times do
40
- outputs << exec
41
- end
42
- else
43
- return exec
38
+ Cfg[:execution_count].times do
39
+ outputs << make_exec
44
40
  end
45
41
  end
46
42
 
47
- outputs.join("\r")
43
+ result = outputs.join("\r")
44
+ manufacture do |format|
45
+ format.html { '<div class="console">' + result + '</div>' }
46
+ format.csv { result }
47
+ format.xls { result }
48
+ end
48
49
  end
49
50
 
50
51
  private
@@ -60,15 +61,14 @@ module Reviser
60
61
  # might not be a good idea regarding
61
62
  # security
62
63
  #
63
- def exec(param = nil)
64
+ def make_exec param = ''
64
65
  program = (Cfg.has_key? :program_name) && Cfg[:program_name] || find_executable
65
66
 
66
67
  return 'Program not found' unless program != nil
67
68
 
68
69
  program = "#{Cfg[:program_prefix]}#{program}"
69
- argument = (param == nil) && '' || param
70
70
 
71
- cmd = "#{(Cfg.has_key? :execute_command) && Cfg[:execute_command] || ''} #{program} #{argument}"
71
+ cmd = "#{Cfg[:execute_command]} #{program} #{param}"
72
72
  out = exec_with_timeout cmd
73
73
 
74
74
  "$ #{cmd}\r#{out[:stdout]}\r#{out[:stderr]}"
@@ -31,8 +31,11 @@ module Reviser
31
31
 
32
32
  # Where I am ?
33
33
  PWD = File.dirname __FILE__
34
+
35
+ # Path of criteria
36
+ CRITERIA = File.join File.dirname(PWD), 'criteria'
34
37
  # Path of extensions
35
- EXT = File.join File.dirname(File.dirname(PWD)), 'ext'
38
+ EXTENSIONS = File.join File.dirname(File.dirname(File.dirname(PWD))), 'ext'
36
39
 
37
40
  attr_reader :criteria
38
41
  attr_reader :output
@@ -82,7 +85,7 @@ module Reviser
82
85
  @logger.h2 Logger::INFO, "Modules of #{directory}"
83
86
  modules = Dir[File.join(directory, regex)]
84
87
 
85
- namespace = directory == EXT && 'Reviser::Extensions' || 'Reviser::Criteria'
88
+ namespace = directory == EXTENSIONS && 'Reviser::Extensions' || 'Reviser::Criteria'
86
89
  modules.each do |m|
87
90
  require_relative m
88
91
  ext = File.extname m
@@ -146,7 +149,7 @@ module Reviser
146
149
  PWD = File.dirname __FILE__
147
150
 
148
151
  # Path of label.yml file
149
- LABELS = File.join(File.dirname(File.dirname(PWD)), 'labels.yml')
152
+ LABELS = File.join File.dirname(File.dirname(File.dirname(PWD))), 'labels.yml'
150
153
 
151
154
  #
152
155
  # Enable to associate a label to a criterion (method).
File without changes
@@ -5,6 +5,8 @@
5
5
  # @author Renan Strauss
6
6
  # @author Yann Prono
7
7
  #
8
+ require_relative '../result'
9
+
8
10
  module Reviser
9
11
  module Helpers
10
12
  module Project
@@ -18,10 +20,7 @@ module Reviser
18
20
 
19
21
  # Check if the project has all files needed
20
22
  def missing_files
21
- return [] unless Cfg =~ :required_files
22
-
23
23
  dir = Dir['*']
24
-
25
24
  #
26
25
  # Check if there is any regexp
27
26
  # If it's the case, if any file
@@ -37,17 +36,23 @@ module Reviser
37
36
  Cfg[:required_files] - dir
38
37
  end
39
38
 
40
- #
41
- # @return all the files in the project's folder
42
- #
43
- def files
44
- Dir.glob("**/*").select { |f| (File.file?(f)) }
45
- end
39
+ #
40
+ # @return all the files in the project's folder
41
+ #
42
+ def files
43
+ Dir.glob("**/*").select { |f| (File.file?(f)) }
44
+ end
46
45
 
47
- def sources
48
- files.select { |f| Cfg[:extension].include? File.extname(f) }
49
- end
46
+ def sources
47
+ files.select { |f| Cfg[:extension].include? File.extname(f) }
48
+ end
50
49
 
50
+ def manufacture &block
51
+ format = Result.new
52
+ block.call format
53
+
54
+ format
55
+ end
51
56
 
52
57
  # This modules is used to scan the name of project
53
58
  # in order to get all students who worked.
File without changes
@@ -42,9 +42,8 @@ module Reviser
42
42
 
43
43
  # In case of someone want to use methods of standard Logger ...
44
44
  def method_missing(m, *args, &block)
45
- @logger.send(m,*args, &block)
45
+ @logger.send m, *args, &block
46
46
  end
47
-
48
47
  end
49
48
  end
50
49
  end
@@ -65,7 +65,7 @@ module Reviser
65
65
  def header
66
66
  add_tag "<!DOCTYPE html><html><head>
67
67
  <meta charset= \"UTF-8\">
68
- <link rel=\"stylesheet\" href=\"#{File.expand_path(File.join(Cfg[:res_dir],'/css/style_logs.css'))}\" />
68
+ <link rel=\"stylesheet\" href=\"#{Cfg.resource('/css/style_logs.css').to_path}\" />
69
69
  <title>#{@basename} logs</title>
70
70
  </head>\n<body>
71
71
  <header>
@@ -0,0 +1,30 @@
1
+ #
2
+ # This class represents an analysis result
3
+ # It allows us to easily output well-formatted results for certain output formats
4
+ # (eg HTML)
5
+ #
6
+ module Reviser
7
+ class Result
8
+ #
9
+ # In case no call to manufacture was made,
10
+ # Checker will create a result with the same
11
+ # valeu for all formats
12
+ #
13
+ def initialize data = nil
14
+ if data != nil
15
+ Cfg[:out_format].each do |format|
16
+ instance_variable_set("@#{format}".to_sym, data)
17
+ end
18
+ end
19
+ end
20
+
21
+ #
22
+ # Does the magic ;-)
23
+ #
24
+ def method_missing m, *args, &block
25
+ format = "@#{m}".to_sym
26
+
27
+ block_given? && instance_variable_set(format, block[]) || instance_variable_get(format)
28
+ end
29
+ end
30
+ end
data/lib/reviser.rb CHANGED
@@ -11,12 +11,12 @@
11
11
  require 'mkmf'
12
12
  require 'colorize'
13
13
 
14
- require_relative 'component'
15
- require_relative 'config'
14
+ require_relative 'reviser/component'
15
+ require_relative 'reviser/config'
16
16
 
17
- require_relative 'helpers/git'
18
- require_relative 'helpers/project'
19
- require_relative 'helpers/system'
17
+ require_relative 'reviser/helpers/git'
18
+ require_relative 'reviser/helpers/project'
19
+ require_relative 'reviser/helpers/system'
20
20
 
21
21
  module Reviser
22
22
  class Reviser
@@ -25,24 +25,24 @@ module Reviser
25
25
 
26
26
  #
27
27
  # Adds an entry with the specified data.
28
- # At this time, we assume the user has given us
29
- # a Cfg that makes sense.
30
- # TODO : check data
31
28
  #
32
29
  def self.load(data)
30
+ raise ArgumentError unless data.has_key?(:component)
31
+
32
+ data[:input_from] ||= nil
33
33
  data[:local] ||= false
34
34
 
35
35
  @@loaded_components.store data[:component],
36
36
  {
37
- :inputFrom => data[:inputFrom],
37
+ :input_from => data[:input_from],
38
38
  :local => data[:local],
39
39
  :data => nil
40
40
  }
41
41
  end
42
42
 
43
43
  def self.setup(config_file)
44
- @@setup = true
45
44
  Cfg.load config_file
45
+ @@setup = true
46
46
  end
47
47
 
48
48
  #
@@ -50,7 +50,7 @@ module Reviser
50
50
  # The exection order is based on the loading order.
51
51
  #
52
52
  def self.run
53
- raise ArgumentError unless @@setup
53
+ raise RuntimeError unless @@setup
54
54
 
55
55
  if Cfg.has_key?(:options) && Cfg[:options].has_key?(:log_dir)
56
56
  FileUtils.mkdir Cfg[:options][:log_dir] unless Dir.exist? Cfg[:options][:log_dir]
@@ -63,12 +63,12 @@ module Reviser
63
63
  @@loaded_components.each do |comp, conf|
64
64
  puts "Reviser is now running "+"#{Reviser.titleize comp}".green + "..."
65
65
 
66
- require_relative "components/#{comp}" unless conf[:local]
66
+ require_relative "reviser/components/#{comp}" unless conf[:local]
67
67
 
68
- namespace = conf[:local] && '' || 'Components'
69
- param = ((conf[:inputFrom] != nil) && @@loaded_components[conf[:inputFrom]][:data]) || nil
68
+ namespace = conf[:local] && '' || 'Components::'
69
+ param = ((conf[:input_from] != nil) && @@loaded_components[conf[:input_from]][:data]) || nil
70
70
 
71
- c = eval("#{namespace}::#{Reviser.titleize comp}").new param
71
+ c = eval("#{namespace}#{Reviser.titleize comp}").new param
72
72
 
73
73
  @@loaded_components[comp][:data] = c.work
74
74
 
@@ -111,5 +111,7 @@ td.user-name {
111
111
  border: 3px double #CCCCCC;
112
112
  padding: 10px;
113
113
 
114
- height: 100%;
114
+ max-height: 800px;
115
+ max-width: 650px;
116
+ overflow: auto;
115
117
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "name" : "Chuck Norris",
3
+ "id" : "0"
4
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes