fake graph for root page
authorMarcel Hlopko <marcel.hlopko@gmail.com>
Thu, 20 Jun 2013 23:31:53 +0200
changeset 63 33ab7e8188d0
parent 62 f5e06b5fc065
child 64 db49a0739ce5
fake graph for root page
web/app/assets/javascripts/application.js
web/app/assets/javascripts/charts.js
web/app/controllers/index_controller.rb
web/app/views/index/_benchmarks_table.html.erb
web/app/views/index/index.html.erb
web/example.results
--- a/web/app/assets/javascripts/application.js	Thu Jun 20 22:40:07 2013 +0200
+++ b/web/app/assets/javascripts/application.js	Thu Jun 20 23:31:53 2013 +0200
@@ -14,8 +14,16 @@
 //= require jquery.ui.all
 //= require twitter/bootstrap
 //= require jquery_ujs
+//= require flot/jquery.flot
+//= require flot/jquery.flot.pie
+//= require flot/jquery.flot.time
+//= require flot/jquery.flot.stack
+//= require charts
 //= require_self
 
+jQuery.fn.exists = function() {
+	return this.length>0;
+}
 
 function notify_success(message) {
 	show_flash(message, "success");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/app/assets/javascripts/charts.js	Thu Jun 20 23:31:53 2013 +0200
@@ -0,0 +1,408 @@
+
+/**
+ * global variables
+ */
+var globalDayNames = ['Ned\u011ble', 'Pond\u011blí', 'Úterý', 'St\u0159eda', '\u010ctvrtek', 'Pátek', 'Sobota'];
+var globalDayNamesShort = ['Ne', 'Po', 'Út', 'St', '\u010ct', 'Pá', 'So'];
+var globalMonthNames = ['Leden', 'Únor', 'B\u0159ezen', 'Duben', 'Kv\u011bten', '\u010cerven', '\u010cervenec',
+'Srpen', 'Zá\u0159í', '\u0158íjen', 'Listopad', 'Prosinec'];
+var globalMonthNamesShort = ['Led', 'Úno', 'B\u0159e', 'Dub', 'Kv\u011b', '\u010cern', '\u010cerc',
+'Srp', 'Zá\u0159', '\u0158íj', 'Lis', 'Pro'];
+var ua = {};
+//array with objects {plot: flot, data: data}
+ua.flots = new Array();
+
+/**
+ * Display charts by Piety plug-in
+ */
+function pietyCharts() {
+    $(".piety.pie-chart").each(function(){
+        var chart = $(this);
+        if(processMultipleCall(chart)){
+            chart.peity("pie",{
+                diameter: chart.width(),
+                colours: ["#fff4dd", "#ff9900","#ADCCDA","#CCAA00"]
+            }); 
+        }
+    });
+    $(".piety.line-chart").each(function(){
+        var chart = $(this);
+        if(processMultipleCall(chart)){
+            chart.peity("line",{
+                width: chart.width()
+            }); 
+        }
+    });
+    $(".piety.bar-chart").each(function(){
+        var chart = $(this);
+        if(processMultipleCall(chart)){
+            chart.peity("bar",{
+                width: chart.width()
+            }); 
+        }
+    });
+    
+    /**
+ * find out whether chart was already generated. If no or is empty, generates new one
+ */
+    function processMultipleCall(object) {
+        if(!object.children("canvas").exists() || parseInt(object.children("canvas").attr("width"))==0){
+            if(object.children("canvas").exists()){
+                object.children("canvas").remove();
+            }
+            return true;
+        }
+        else{
+            return false;
+        }
+    }
+}
+
+/**
+ * Display charts by Flot plug-in
+ */
+function flotCharts() {
+    //render pie chart
+    $(".flot.pie-chart").each(function(){
+        var chart = $(this);
+        chart.css("min-height",(chart.width()*.75)+"px");
+        var showValues = chart.attr("data-show-values") != undefined ? true : false;
+        var dataArray = loadData(chart);
+        var options = {
+            series: {
+                pie: {
+                    show: true
+                }
+            },
+            grid: {
+                hoverable: showValues
+            }
+        };
+        $.plot(chart, dataArray,options);
+        //whether we want to show values -> add value placeholder and bind it
+        showChartValues(chart);
+        ua.flots.push({
+            placeholder: chart,
+            data:dataArray,
+            options:options
+        });
+        
+    });
+    
+    //rendre line chart
+    $(".flot.line-chart").each(function(){
+        var chart = $(this);
+        //        if(chart.height() == 0){
+        chart.css("min-height",(chart.width()*1/2)+"px");
+        //        }
+        var dataArray = loadData(chart);
+        var options = {
+            xaxis: {},
+            grid: {
+                hoverable: true
+            }
+        };
+        if(chart.hasClass("time-chart")){
+            options.xaxis.mode = "time";
+        }
+        $.plot(chart, dataArray,options);
+        var previousPoint = null;
+        chart.on("plothover", function(event, pos, obj){
+            if (obj) {
+                if (previousPoint != obj.dataIndex) {
+                    previousPoint = obj.dataIndex;                    
+                    $("#js-chart-tooltip").remove();
+                    showTooltip(obj.pageX, obj.pageY,obj.series.data[obj.dataIndex][1]);
+                }
+            }
+            else {
+                $("#js-chart-tooltip").remove();
+                previousPoint = null;            
+            }
+        });
+        ua.flots.push({
+            placeholder: chart,
+            data:dataArray,
+            options:options
+        });
+    });
+    
+    
+    //rendre line chart
+    $(".flot.bar-chart").each(function(){
+        var chart = $(this);
+        //        if(chart.height() == 0){
+        chart.css("min-height",(chart.width()*1/2)+"px");
+        //        }
+        var dataArray = loadData(chart);
+        var plot,options = {
+            series:{
+                bars: {
+                    barWidth: .9,
+                    align: "center"
+                },
+                stack: true
+            }
+        };
+        if(chart.attr("data-stack").bool()){
+            options.series.stack = true;
+        }
+        $.plot(chart, dataArray,options);
+        ua.flots.push({
+            placeholder: chart,
+            data:dataArray,
+            options:options
+        });
+    });
+    
+    /*
+     *loads data from DOM object. Data can be in data- attributes or in table
+     */
+    function loadData(object){
+        var labels, data, types;
+        //data in table
+        if(object.children("table").exists()){
+            var table = object.children("table");
+            //load labels
+            labels = [];
+            data = new Array();
+            types = new Array();
+            //choose all colums except first one -> not describing data
+            table.find("thead th").not(":first-child").each(function(){
+                labels.push($(this).text());
+                data.push(new Array());
+                //whether lines or bars (set by data-type)
+                //default is according chart type
+                var def = "lines";
+                if (object.hasClass("line-chart")) {
+                    def = "lines";
+                }
+                else if(object.hasClass("bar-chart")){
+                    def = "bars";
+                }
+                types.push($(this).attr("data-type") != undefined ? $(this).attr("data-type"): def);
+            });
+            var row,index;
+            //load data
+            var isTime = object.hasClass("time-chart");
+            table.find("tbody tr").each(function(){
+                row = $(this);
+                if(isTime){
+                    index = parseInt(row.children("th").attr("data-timestamp"))*1000; //*1000 because timestamp in JS is in ms
+                }else{
+                    index = parseInt(row.children("th").text());
+                }
+                var j = 0;
+                row.children("td").each(function(){
+                    data[j].push([index,parseInt($(this).text())]);
+                    j++;
+                });
+            }); 
+            var resultData = new Array();
+            var showLines, showBars;
+            for(var i = 0;i<labels.length;i++){
+                showBars = types[i] == "bars" ? true : false;
+                showLines = types[i] == "lines" ? true : false;
+                resultData.push({
+                    label: labels[i],
+                    data: data[i],
+                    lines: {
+                        show: showLines
+                    },
+                    bars: {
+                        show: showBars
+                    },
+                    points: {
+                        show: showLines //points only on-lines
+                    }
+                    
+                });
+            }
+            return resultData;
+        }
+        //data in data- attrs
+        else{
+            labels = object.attr("data-labels").split(";");
+            data = object.attr("data-values").split(";");
+            if(labels.length != data.length){
+                console.log("Jiný počet prvků v poli popisků a v poli dat");
+                return [];
+            }
+            var dataArray = [];
+            for( var i = 0; i<labels.length; i++){
+                dataArray[i] = {
+                    label: labels[i], 
+                    data: parseInt(data[i])
+                }
+            }
+            return dataArray;
+        }
+    }
+    
+    /**
+ *shows chart point tooltip
+ *from: http://people.iola.dk/olau/flot/examples/interacting.html
+ */
+    function showTooltip(x, y, contents) {
+        $('<div id="js-chart-tooltip">' + contents + '</div>').css( {
+            position: 'absolute',
+            display: 'none',
+            top: y + 5,
+            left: x + 5,
+            border: '1px solid #fdd',
+            padding: '2px',
+            'background-color': '#fee',
+            opacity: 0.80
+        }).appendTo("body").fadeIn(200);
+    }
+    
+}
+
+/**
+ * shows values on pie chart
+ */
+function showChartValues(chart) {
+    chart.append($("<div class='value-placeholder'> </div>"));
+    chart.on("plothover", function(event, pos, obj){
+        if (!obj){
+            return;
+        }
+        var percent = parseFloat(obj.series.percent).toFixed(2);
+        //this == chart
+        $(this).find(".value-placeholder").html(obj.series.data[0][1] + ' <small>('+percent+'%)</small>').fadeIn();
+    });
+}
+    
+/**
+ * refresh flot chart
+ */
+function refreshCharts() {
+    var flot;
+    for(var i = 0; i<ua.flots.length;i++){
+        flot = ua.flots[i];
+        $.plot(flot.placeholder, flot.data,flot.options);
+    }
+    //bind showing values again
+    $(".pie-chart.flot[data-show-values='true']").each(function(){
+        showChartValues($(this));
+    });
+}
+
+/**
+ * Manage remove prompts
+ */
+function removePrompt() {
+    $("body").on("click",".js-remove-prompt",function(e){
+        e.preventDefault();
+        var prompt = $("<div class='ua-prompt ua-remove-prompt'>"+
+            "<a href='" + $(this).attr("data-target") + "' class='btn btn-danger btn-mini icon-trash'>Smazat</a>"+
+            "<a href='#close' class='btn btn-link btn-mini'>Zrušit</a>"+
+            "</div>");
+        prompt.find("a[href='#close']").one("click",function(e){
+            e.preventDefault();
+            hidePrompt(prompt);
+        });
+        prompt.find("a[href='"+$(this).attr("data-target")+"']").one("click",function(){
+            //cannot use the same method as for #close button - propagation is needed here
+            hidePrompt(prompt);
+        });
+        prompt.appendTo("body");
+        var x, y;
+        x = $(this).offset().left + $(this).width() - prompt.width();
+        y = $(this).offset().top-5; //to make it nicier
+        prompt.css({
+            left: x+"px", 
+            top:y+"px"
+        });
+        prompt.show("slide", {
+            direction:"right"
+        },300);
+    });
+    
+    /**
+     * hide prompt and remove it from DOM
+     */
+    function hidePrompt(prompt) {
+        prompt.hide("slide", {
+            direction:"right"
+        },500,function(){
+            prompt.remove();
+        });
+    }
+}
+
+/**
+ * Functions which changes running time
+ */
+function runningTime() {
+    var currentTime = new Date().getTime();
+    var time;
+    $(".ua-time-running[data-start]").each(function(){
+        time = new Date(currentTime - parseInt($(this).attr("data-start")) - 3600000); //-1h = 60*60*1000
+        $(this).html(time.toLocaleTimeString());
+    });
+}
+
+/**
+ * Bootstrap pop-over handlers
+ */
+function popovers() {
+    $("body").on("click",".popover-link",function(){
+        var clicked = $(this);
+        clicked.popover({
+            html:true
+        });
+        clicked.popover("show");
+        //any click will close the popover
+        $("body").one("click",function(){
+            clicked.popover("hide");
+        });
+    });
+}
+
+/**
+ * Extend default Bootstrap tabs behavior
+ */
+function tabs() {
+    //re-run piety charts init when tab is shown
+    $('.shows-charts[data-toggle="tab"]').on('shown', function (e) {
+        pietyCharts();
+    })
+    
+    //if there's a tab with id from url, show it
+    if($("a[href='"+window.location.hash+"']")){
+        $("a[href='"+window.location.hash+"']").tab("show");
+    }
+}
+
+
+/**
+ * Calls all methods which shoul be called after screen si resized
+ */
+function viewportResized() {
+    refreshCharts();
+    convertMenu();
+}
+
+/**
+ * Bind jQuery chosen plug-in
+ */
+function chosen() {
+    //pokud bude vic polozek jak 10, zobrazi i vyhledavani
+    $("select.js-chosen:visible").chosen({
+        disable_search_threshold: 10
+    }); 
+}
+
+
+$(document).ready(function(){
+    pietyCharts();
+    flotCharts();
+    setInterval("runningTime()",1000);
+    removePrompt();
+    popovers();
+    tabs();
+    viewportResized();
+    $(window).on("debouncedresize", viewportResized);
+});
+
--- a/web/app/controllers/index_controller.rb	Thu Jun 20 22:40:07 2013 +0200
+++ b/web/app/controllers/index_controller.rb	Thu Jun 20 23:31:53 2013 +0200
@@ -1,4 +1,33 @@
 class IndexController < ApplicationController
   def index
+    @current_results = fake_data
+  end
+
+  private 
+
+  def fake_data
+    [ {"benchmark"=> {
+      "class"=> "BenchmarkMicro",
+      "selector"=> "ackermann"	},
+      "times"=> [1281,1359,1437,1391,1500],
+      "parameters"=> {}},
+
+    {"benchmark"=> {
+        "class"=> "BenchmarkMicro",
+        "selector"=> "ary"},
+        "times"=> [1059,1056,1059,1059,1057],
+        "parameters"=> {}},
+
+    {"benchmark"=> {
+          "class"=> "BenchmarkMicro",
+          "selector"=> "hsh"},
+          "times"=> [1422,1438,1421,1407,1422],
+          "parameters"=> {}},
+
+    {"benchmark"=> {
+            "class"=> "BenchmarkMicro",
+            "selector"=> "strcat"},
+            "times"=> [1312,1203,1125,984,1188],
+            "parameters"=> {}}]
   end
 end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/app/views/index/_benchmarks_table.html.erb	Thu Jun 20 23:31:53 2013 +0200
@@ -0,0 +1,22 @@
+<div class="<%= "line-chart flot bar-chart" if make_chart %>" data-stack="false" >
+    <table class="table table-condensed">
+        <thead>
+            <tr>
+                <th>Benchmarks</th>
+                <% results.each do |result| %> 
+                  <th><%= "#{result["benchmark"]["selector"]}" %></th>
+                <% end %>
+            </tr>
+        </thead>
+        <tbody>
+          <% 5.times do |index| %>
+            <tr>
+              <th><%= index + 1 %></th>
+              <% results.each do |result| %> 
+                <td><%= result["times"][index] %></td>
+              <% end %>
+            </tr>
+          <% end %>
+        </tbody>
+    </table>
+</div>
--- a/web/app/views/index/index.html.erb	Thu Jun 20 22:40:07 2013 +0200
+++ b/web/app/views/index/index.html.erb	Thu Jun 20 23:31:53 2013 +0200
@@ -1,8 +1,14 @@
 <%= currently_at "index" %>
 
-<h1>Calipel</h1>
-<p>
-Simple micro-benchmarking framework inspired by SUnit a Caliper
-</P>
+<%= image_tag "logo.png", width: '400px', class: "pull-right" %>
 
-<h2>Current Test Results</h2>
+<div class="span6">
+  <h1>Calipel</h1>
+  <p>
+    Simple micro-benchmarking framework inspired by SUnit a Caliper
+  </P>
+  <h2>Current Test Results</h2>
+
+  <%= render 'index/benchmarks_table', results: @current_results, make_chart: false %>
+  <%= render 'index/benchmarks_table', results: @current_results, make_chart: true %>
+</div>
--- a/web/example.results	Thu Jun 20 22:40:07 2013 +0200
+++ b/web/example.results	Thu Jun 20 23:31:53 2013 +0200
@@ -1,4 +1,4 @@
-{"outcomes": [
+[
 	{"benchmark": {
 			"class": "BenchmarkMicro",
 			"selector": "ackermann"	},
@@ -21,4 +21,4 @@
 			"class": "BenchmarkMicro",
 			"selector": "strcat"},
 	"times": [1312,1203,1125,984,1188],
-	"parameters": {}}]}
+	"parameters": {}}]