Project

reviser

0.0
No commit activity in last 3 years
No release in over 3 years
A semi-automatic tool for students' projects evaluation
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 0.7.5, ~> 0.7
>= 1.1.7, ~> 1.1
>= 0.19.1, ~> 0.19
 Project Readme

Reviser

###Description

Reviser is a semi-automatic tool for student's projects evaluation, written in Ruby.

###Installation

Download and install the gem with the following command line.

gem install reviser

###Basic usage

To create a new workspace in the current directory, simply run the following command in a terminal:

reviser init .

Create		res
Create		type
Create		config.yml
Create		labels.yml

You see reviser has created res and type/example folders for you. Now you'll have to customize config.yml to your own needs, and add a type/your_project.yml

To perform the analysis, simply run:

reviser work

###How it works

Our tool is divided into 4 main components :

Component Role
Archiver Extracting all computing projects
Organiser Parsing students names and renaming directories appropriately
Checker Running the analysis based upon selected criteria and extensions
Generator Generating the analysis results in various formats

The basic idea is that each component can receive data from any of the components run before it. It shall requests that input upon loading. The work command actually runs the above components with the appropriate input data (e.g. Generator relies on Checker results).

###Configuration

This tool was thought to be very adaptable, thus it relies on YAML configuration files.

###Global configuration Lives in config.yml.

Key Description Values Required
src Path to the archive containing projects checkbox.png
dest Path to a directory where projects will be extracted checkbox.png
projects_names Naming convention for projects ^GROUP_NAME_NAME ^GROUP_NAME(_NAME)* ^TP_NAME_FIRSTN checkbox.png
type The type of the project my_project (type/my_project.yml must exist) checkbox.png
criteria The criteria you want for analysis all_files src_files lines_count comments_count compile execute checkbox.png
extensions The list of extensions you want for analysis See below
create_git_repo Whether to create a git repository for each project or not (requires git gem) Default false
out The name of the analysis output file Default results
out_format The formats that will be generated Default csv html (xls also available, but requires spreadsheet gem)
options A hash to set options for logging :log_dir :log_mode

###Project configuration Lives in type/my_project.yml.

Key Description Values Required
language The target language C Java HTML Ruby checkbox.png
timeout In seconds. Compilation and execution will halt if not completed within the defined timeout Default 4
required_files A list of required files Tip: you can use regular expressions
preferred_build_command The command to build the program with make
execute_command The name of the interpreter java ruby
program_prefix The program prefix pkg. for Java
program_name The name of the program a.out Main
execution_count The amount of times to execute the program Default 1
execution_value The optional parameter to pass to the program when executing A list of values whose length shall be execution_count or 1. It can contains paths for files located in resources folder

###Labels configuration

Each criterion is associated with a label. A label is some words, describing the criterion's result. For example, a criterion which checks the existence of a Makefile could have a label like 'Existence of Makefile'.

By default, labels are generated with the name of the called method. You have the possibility to customize this label thanks to the command line tool:

reviser add makefile? 'Existence of makefile'
#            method       associated label

Labels are stored in your workspace, in a file called labels.yml. You can also edit them by hand if you prefer.

###Extensions Extensions are in fact Criteria we didn't want to include into reviser's core. Reviser's core aims to rely as much as possible on native Ruby APIs to ensure its portability. That's why Extensions exist: they basically are Criteria which relies on platform-spefic-features.

As of now, there are 2 extensions:

Extension Description Add it to your workspace extensions
Valgrind Runs a memcheck through system call to valgrind memleaks
WebValidators Validates HTML and CSS through W3C API calls (requires w3c_validators gem) validate_web

###Working on your own

If you have very special needs, you may need to create your own components or extensions. You'll then need to load your components at the right time, and register your extensions for them to be available.

####Custom components

We're going to show you how to create a custom generator that will generate a nice-looking HTML table using jQuery dataTables.

example/my_generator.rb

#
# This is a simple component showing how to extend Reviser
# We are going to build a custom HTML generator with jQuery :-)
#
require 'reviser'

class MyGenerator < Reviser::Component
	#
	# We're expecting results from Checker as data
	#
	def initialize data
		super data
		#
		# We want the HTML output
		#
		@data.each do |project, results|
			results.each do |criterion, value|
				@data[project][criterion] = value.html
			end
		end
	end

	def run
		#
		# Get our template file
		#
		template = resource('html/results_template.html').read

		out = '<thead><tr>'
		#
		# Each criterion as headings
		#
		@data.values.first.keys.unshift.unshift('Projet').each { |crit| out += "<th>#{crit}</th>" }
		
		out += '</tr></thead><tbody>'
 		# Values for each project as rows
		@data.keys.each do |proj|
			out += "<tr><th>#{proj}</th>"
			@data[proj].each do |k, v|
				out += "<td>#{v.to_s.strip}</td>"
			end
			out += '</tr>'
		end
		out += '</tbody>'

		#
		# Kind of a hacky template engine
		# We replace placeholders with actual values
		#
		template.sub! '[DATA]', out
		template.sub! '[MAINCSS_PATH]', resource('css/main.css').to_path

		File.open('my_results.html', 'w') { |f| f.write template }
  end
end

example/res/my_generator/html/results_template.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset= "UTF-8">
		<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
		<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/plug-ins/f2c75b7247b/integration/bootstrap/3/dataTables.bootstrap.css">
		<link rel="stylesheet" type="text/css" href="[MAINCSS_PATH]">
		<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
		<script type="text/javascript" src="http://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
		<script type="text/javascript" src="http://cdn.datatables.net/plug-ins/f2c75b7247b/integration/bootstrap/3/dataTables.bootstrap.js"></script>
		<title>My results</title>
		<script type="text/javascript">
			$(document).ready(function() {
				$('#results').dataTable({"dom":' <"search"fl><"top">rt<"bottom"ip><"clear">'});
			});
		</script>
	</head>
	<body>
		<table id="results">
			[DATA]
		</table>
		<script type="text/javascript">
			$('#results').removeClass('display').addClass('table table-striped table-bordered');
		</script>
	</body>
</html>

####Custom extensions

Now let's create a custom criterion ! This one is very simple : it will calculate project's size thanks to filesize gem.

Creating an extension is as simple as creating a module. In fact, when you register that module as an extension, its methods become available for you to add in extensions configuration key.

example/my_extension.rb

require 'find'
require 'reviser'

#
# A custom criteria for reviser
#
module MyExtension
	#
	# This helper has the 'sources' methods
	# that allow you to retrieve all sources
	# files (files matching language extension)
	# as well as the 'manufacture' method,
	# needed to adapt results to out format
	#
	include Reviser::Helpers::Project

	#
	# Keep in mind that this method will be run
	# in each project's directory !
	# (that's why we use FileUtils.pwd)
	#
	def project_size
		#
		# That's the way we require gems without worrying
		# of them being installed or not !
		# require_gem is in global scope, and will raise an
		# exception if the given gem is not installed.
		# It will include it otherwise
		#
		unless defined? Filesize
			require_gem 'filesize'
		end

		size_in_bytes = size(FileUtils.pwd)
		results = Filesize.from("#{size_in_bytes} B").pretty
		#
		# The manufacture method excepts
		# a block which must describe the result contents
		# for EACH format.
		# You can also return raw data, then it'll be as it is
		# for all formats.
		#
		manufacture do |format|
			format.html { '<span style="font-weight:bold;">' + results + '</span>' }
			format.csv { results }
			format.xls { results }
		end
	end

	private
		#
		# Returns the size of all the given
		# files (even if there are also dirs)
		# in bytes
		#
		def size(dir)
			bytes = 0
			Find.find(*Dir["#{dir}/**/*"]) { |f| bytes += File.stat(f).size }

			bytes.to_f
		end
end

Putting it together

example/config.yml

extensions:
  - project_size

example/my_app.rb

This file shows how to plug your custom component into reviser's workflow as well as how to make your custom extension available.

require 'reviser'

require_relative 'my_extension'
require_relative 'my_generator'

module MyApp
	include Reviser

	def self.run config_file = 'config.yml'
		#
		# Setup reviser
		#
		Reviser::setup config_file

		#
		# You can now use MyExtension's methods for analysis
		#
		Reviser::register :extension => 'MyExtension'
		
		#
		# You can load any built-in component (archiver, organiser, checker, generator)
		# But be aware that they have to be ran in this order, and that
		# organiser takes input from archiver, checker from organiser and generator from checker
		# If you don't respect that, nothing will work.
		# But you can run your component at any step, this won't break the process.
		#
		Reviser::load :component => 'archiver'
		Reviser::load :component => 'organiser', :input_from => 'archiver'
		Reviser::load :component => 'checker', :input_from => 'organiser'
		#
		# We run our custom generator instead :-)
		#
		# With :local => true, we tell reviser not to look for our component
		# in its core ones but to let us include it ourselves instead
		#
		Reviser::load :component => 'my_generator', :input_from => 'checker', :local => true

		# Reviser::load :component => 'generator', :input_from => 'checker'

		#
		# Run reviser
		#
		Reviser::run
	end
end

example/main.rb

require_relative 'my_app'

#
# You can then run your app (don't forget you still need to be in a reviser workspace,
# so type/ and res/ folders must exist, as well as config.yml)
#
MyApp::run

Team

Anthony Cerf

Yann Prono

Romain Ruez

Renan Strauss

Other stuff

Question Answer
Requires Ruby 1.9.3 or later