
https://svn.lrde.epita.fr/svn/ranch/trunk Index: ChangeLog from Nicolas Desprès <nicolas.despres@lrde.epita.fr> Draw regression graph. * web/ranch/app/controllers/graph_controller.rb: New. Collect data and send them to the grapher. * web/ranch/test/functional/graph_controller_test.rb: New. Test the graph controller. * web/ranch/app/helpers/graph_helper.rb: New. Add a tag that helps to draw a regression graph in a view. * web/ranch/lib/grapher.rb: New. Generate a graph using `ruby-gdchart'. * web/ranch/app/controllers/graph_form_controller.rb: Add the draw request. * web/ranch/test/functional/graph_form_controller_test.rb: . * web/ranch/app/views/graph_form/index.rhtml: Draw the graph. * web/ranch/app/models/output.rb: New. The model for the outputs table. * web/ranch/test/unit/output_test.rb: New. Test the model. * web/ranch/test/fixtures/outputs.yml: New. Add some fixtures. * web/ranch/test/fixtures/benches.yml, * web/ranch/test/fixtures/projects.yml: Update to the new DB schema. * web/ranch/app/models/bench.rb: Add the relationship with the outputs table. * web/ranch/config/environment.rb: Require some libs. * web/ranch/db/schema.rb: Add the outputs table. app/controllers/graph_controller.rb | 39 ++++++++++++++++++++++++++ app/controllers/graph_form_controller.rb | 11 ++++++- app/helpers/graph_helper.rb | 18 ++++++++++++ app/models/bench.rb | 1 app/models/output.rb | 5 +++ app/views/graph_form/index.rhtml | 13 +++++++- config/environment.rb | 3 ++ db/schema.rb | 11 +++++++ lib/grapher.rb | 27 ++++++++++++++++++ test/fixtures/benches.yml | 19 ++++++------ test/fixtures/outputs.yml | 12 ++++++++ test/fixtures/projects.yml | 3 ++ test/functional/graph_controller_test.rb | 19 ++++++++++++ test/functional/graph_form_controller_test.rb | 20 ++++++++++++- test/unit/output_test.rb | 10 ++++++ 15 files changed, 196 insertions(+), 15 deletions(-) Index: web/ranch/test/unit/output_test.rb --- web/ranch/test/unit/output_test.rb (revision 0) +++ web/ranch/test/unit/output_test.rb (revision 0) @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class OutputTest < Test::Unit::TestCase + fixtures :outputs + + # Replace this with your real tests. + def test_truth + assert_kind_of Output, outputs(:first) + end +end Index: web/ranch/test/functional/graph_controller_test.rb --- web/ranch/test/functional/graph_controller_test.rb (revision 0) +++ web/ranch/test/functional/graph_controller_test.rb (revision 0) @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/../test_helper' +require 'graph_controller' + +# Re-raise errors caught by the controller. +class GraphController; def rescue_action(e) raise e end; end + +class GraphControllerTest < Test::Unit::TestCase + def setup + @controller = GraphController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + # Replace this with your real tests. + def test_truth + #FIXME: test me + assert true + end +end Index: web/ranch/test/functional/graph_form_controller_test.rb --- web/ranch/test/functional/graph_form_controller_test.rb (revision 12) +++ web/ranch/test/functional/graph_form_controller_test.rb (working copy) @@ -13,13 +13,29 @@ @response = ActionController::TestResponse.new end - # Replace this with your real tests. - def test_truth + def test_index get :index, { :project_id => 1, :bench_name => 'determinize' } assert_response :success assert_template 'index' assert_not_nil assigns(:project) assert_not_nil assigns(:bench_name) + assert !assigns(:draw_on) end + + def test_draw + post :draw, { + :project_id => 1, + :bench_name => 'determinize', + :revision => { :start => 0, :stop => 10 } + } + assert_response :success + assert_template 'index' + + assert_not_nil assigns(:project) + assert_not_nil assigns(:bench_name) + assert_not_nil assigns(:revision) + assert assigns(:draw_on) + end + end Index: web/ranch/test/fixtures/outputs.yml --- web/ranch/test/fixtures/outputs.yml (revision 0) +++ web/ranch/test/fixtures/outputs.yml (revision 0) @@ -0,0 +1,12 @@ +<% id = 0 %> + +<% val = 5; (1..10).each do |rev| %> +<%= "determinize_r#{rev}_utime:" %> + id: <%= id += 1 %> + name: utime + value: <%= val += rev %> + unit: sec + bench_id: <%= rev %> + arg_num: 1 +<% end %> + Index: web/ranch/test/fixtures/benches.yml --- web/ranch/test/fixtures/benches.yml (revision 12) +++ web/ranch/test/fixtures/benches.yml (working copy) @@ -1,26 +1,25 @@ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html -<% id = 1 %> +<% id = 0 %> -determinize_r1: - id: <% id += 1 %> - project_id: 1 - name: determinize -determinize_r2: - id: <% id += 1 %> +<% (1..10).each do |rev| %> +<%= "determinize_r#{rev}:" %> + id: <%= id += 1 %> project_id: 1 name: determinize + revision: <%= rev %> +<% end %> quotient: - id: <% id += 1 %> + id: <%= id += 1 %> project_id: 1 name: quotient open: - id: <% id += 1 %> + id: <%= id += 1 %> project_id: 2 name: open close: - id: <% id += 1 %> + id: <%= id += 1 %> project_id: 2 name: close Index: web/ranch/test/fixtures/projects.yml --- web/ranch/test/fixtures/projects.yml (revision 12) +++ web/ranch/test/fixtures/projects.yml (working copy) @@ -2,7 +2,10 @@ vaucanson: id: 1 name: Vaucanson + head_revision: 10 + olena: id: 2 name: Olena + head_revision: 100 Index: web/ranch/app/helpers/graph_helper.rb --- web/ranch/app/helpers/graph_helper.rb (revision 0) +++ web/ranch/app/helpers/graph_helper.rb (revision 0) @@ -0,0 +1,18 @@ +module GraphHelper + + def graph_reg_tag(project_id, bench_name, rev_start, rev_stop, options={}) + url = { + :controller => 'graph', + :action => 'regression', + :project_id => project_id, + :bench_name => bench_name, + :rev_start => rev_start, + :rev_stop => rev_stop + } + options = url.merge(options) + "<img src=\"#{url_for options}\" " + + "class=\"#{options[:class] || 'regression_graph'}\" "+ + "alt=\"Regression graph\" />" + end + +end Index: web/ranch/app/models/bench.rb --- web/ranch/app/models/bench.rb (revision 12) +++ web/ranch/app/models/bench.rb (working copy) @@ -1,5 +1,6 @@ class Bench < ActiveRecord::Base belongs_to :project + has_many :output end Index: web/ranch/app/models/output.rb --- web/ranch/app/models/output.rb (revision 0) +++ web/ranch/app/models/output.rb (revision 0) @@ -0,0 +1,5 @@ +class Output < ActiveRecord::Base + + belongs_to :bench + +end Index: web/ranch/app/controllers/graph_controller.rb --- web/ranch/app/controllers/graph_controller.rb (revision 0) +++ web/ranch/app/controllers/graph_controller.rb (revision 0) @@ -0,0 +1,39 @@ +class GraphController < ApplicationController + + load 'grapher.rb' + + def regression + @project = Project.find params[:project_id] + @bench_name = params[:bench_name] + @output_num = 1 #FIXME: manage several outputs + + values = Bench.find_by_sql "SELECT outputs.value, benches.revision " + + "FROM outputs, benches " + + "WHERE benches.project_id = #{@project.id} " + + "AND benches.name = '#@bench_name' " + + "AND outputs.bench_id = benches.id " + + "AND outputs.arg_num = #@output_num " + + "AND #{params[:rev_start]} <=benches.revision " + + "AND benches.revision <= #{params[:rev_stop]} " + + "ORDER BY benches.revision" + + data = values.collect { |v| v.value.to_f } + labels = values.collect { |v| "r#{v.revision}" } + + filename = "regression_#{@project.name}_#@bench_name" + Tempfile.open(filename) do |f| + File.open(f.path, 'w') do |io| + Grapher.regression(io, + "#{@project.name}: #@bench_name", + "utime(sec)", #FIXME: gather this info from the DB + data, + labels) + end + send_file(f.path, + :disposition => 'inline', + :type => 'image/jpeg', + :filename => "#{filename}.jpg") + end + end + +end Index: web/ranch/app/controllers/graph_form_controller.rb --- web/ranch/app/controllers/graph_form_controller.rb (revision 12) +++ web/ranch/app/controllers/graph_form_controller.rb (working copy) @@ -1,10 +1,19 @@ class GraphFormController < ApplicationController - + helper :graph layout 'ranch' def index @bench_name = params[:bench_name] @project = Project.find params[:project_id] + @draw_on = false + end + + def draw + @bench_name = params[:bench_name] + @project = Project.find params[:project_id] + @revision = params[:revision] + @draw_on = true + render :action => 'index' end end Index: web/ranch/app/views/graph_form/index.rhtml --- web/ranch/app/views/graph_form/index.rhtml (revision 12) +++ web/ranch/app/views/graph_form/index.rhtml (working copy) @@ -13,12 +13,21 @@ <td>Stop</td> </tr> <tr> - <td><%= text_field "revision", "start", "size" => 8, "value" => 0 %></td> - <td><%= text_field "revision", "stop", "size" => 8, "value" => 10 %></td> + <td><%= text_field "revision", "start", "size" => 8, + "value" => 0 %></td> + <td><%= text_field "revision", "stop", "size" => 8, + "value" => @project.head_revision %></td> </tr> </table> </center> </p> <%= submit_tag "Draw" %> <%= end_form_tag %> + +<% if @draw_on %> + <%= graph_reg_tag @project.id, @bench_name, + @revision[:start], @revision[:stop] %> +<% else %> + <%= content_tag "p", "No chart to display - click Draw" %> +<% end %> </div> Index: web/ranch/config/environment.rb --- web/ranch/config/environment.rb (revision 12) +++ web/ranch/config/environment.rb (working copy) @@ -49,3 +49,6 @@ # end # Include your application configuration below \ No newline at end of file +require 'grapher' +require 'tempfile' + Index: web/ranch/db/schema.rb --- web/ranch/db/schema.rb (revision 12) +++ web/ranch/db/schema.rb (working copy) @@ -12,8 +12,19 @@ add_index "benches", ["project_id"], :name => "project_id" + create_table "outputs", :force => true do |t| + t.column "name", :string, :limit => 128, :default => "noname", :null => false + t.column "value", :float, :default => 0.0, :null => false + t.column "unit", :string, :limit => 128, :default => "nounit", :null => false + t.column "bench_id", :integer, :limit => 10, :default => 0, :null => false + t.column "arg_num", :integer, :limit => 8, :default => 1, :null => false + end + + add_index "outputs", ["bench_id"], :name => "bench_id" + create_table "projects", :force => true do |t| t.column "name", :string, :default => "noname", :null => false + t.column "head_revision", :integer, :limit => 10, :default => 0, :null => false end end Index: web/ranch/lib/grapher.rb --- web/ranch/lib/grapher.rb (revision 0) +++ web/ranch/lib/grapher.rb (revision 0) @@ -0,0 +1,27 @@ +require_gem 'ruby-gdchart' + +module Grapher + + def self.regression(io, title, ytitle, data, labels) + gdc = GDChart.new + gdc.title = title + gdc.title_size = GDChart::GIANT + gdc.set_color = [ 0x00FF00 ] + gdc.bg_color = 0xFFFFFF + gdc.xtitle = "Revision" + gdc.ytitle = ytitle + xsize = 600 + ysize = 300 + numsets = 1 + gdc.image_type = GDChart::JPEG + gdc.out_graph(xsize, + ysize, + io, + GDChart::LINE, + labels.size, + labels, + numsets, + data) + end + +end