added stacked graphs
authorForrest Voight <forrest@forre.st>
Tue, 8 May 2012 18:28:43 +0000 (14:28 -0400)
committerForrest Voight <forrest@forre.st>
Tue, 8 May 2012 19:13:27 +0000 (15:13 -0400)
web-static/graphs.html

index e2ce765..2a49a2d 100644 (file)
                 return {"area": top, "mean": bottom==0?null:top/bottom};
             }
             
-            function plot(g, unit, total_unit, lines) {
+            function plot(g, unit, total_unit, lines, stack) {
                 // lines is a list of objects which have attributes data, color, and label
                 
-                var w = 640;
+                var w = 700;
                 var h = 300;
                 var margin_v = 40;
-                var margin_h = 120;
+                var margin_h = 180;
                 
                 var x = d3.time.scale().domain([
                     as_date(d3.min(lines, function(line) { return d3.min(line.data, itemgetter(0)); })),
                     as_date(d3.max(lines, function(line) { return d3.max(line.data, itemgetter(0)); }))
                 ]).range([0 + margin_h, w - margin_h]);
-                var y = d3.scale.linear().domain([
-                    0,
-                    d3.max(lines, function(line) { return d3.max(line.data, itemgetter(1)); } )
-                ]).range([h - margin_v, margin_v]);
                 
                 
                 g.attr("width", w).attr("height", h);
                 g.selectAll("*").remove();
                 
-                var text_boxes = [];
-                for(var i = 0; i < lines.length; ++i) {
-                    var line = lines[i];
-                    var line_type = d3.svg.line().x(compose(x, as_date, itemgetter(0))).y(compose(y, itemgetter(1))).defined(compose(not_null, itemgetter(1)));
-                    g.append("svg:path")
-                        .attr("d", line_type(line.data))
-                        .attr("stroke", line.color)
+                if(stack) {                   
+                    var data = d3.layout.stack()
+                        .x(itemgetter(0))
+                        .y(itemgetter(1))
+                        .values(function(line){ return line.data })
+                        (lines);
+                    
+                    var y = d3.scale.linear().domain([
+                        0,
+                        d3.max(data, function(d) { return d3.max(d.data, function(d) { return d.y0 + d.y; }) })
+                    ]).range([h - margin_v, margin_v]);
+                    
+                    g.selectAll().data(lines).enter().append("svg:path")
+                        .attr("d", function(line){
+                            return d3.svg.area()
+                                .x(function(d) { return x(as_date(d[0])) })
+                                .y0(function(d) { return y(d.y0) })
+                                .y1(function(d) { return y(d.y0 + d.y) })
+                                .defined(compose(not_null, itemgetter(1)))
+                                (line.data)
+                        })
+                        .style("fill", function(line){return line.color})
+                        .attr("stroke", function(line){return line.color})
                         .attr("class", "plotline")
-                        .on("mouseover", function(i) { return function() {
+                        .on("mouseover", function(line, i) {
                             for(var j = 0; j < text_boxes.length; j++)
                                 text_boxes[j][1].attr("opacity", text_boxes[j][0] == i ? 1 : 0.3);
-                        }}(i));
-                    var stats = get_area_mean(line.data);
-                    if(stats.mean != null) {
-                        text_boxes.push([i, g.append("svg:text")
-                            .text(line.label)
-                            .attr("text-anchor", "start")
-                            .attr("dominant-baseline", "central")
-                            .attr("fill", line.color)
-                            .attr("x", w - margin_h + 10)
-                            .attr("y", y(stats.mean) - 12)]);
-                        text_boxes.push([i, g.append("svg:text")
-                            .text("-Mean: " + d3.format(".3s")(stats.mean) + unit)
-                            .attr("text-anchor", "start")
-                            .attr("dominant-baseline", "central")
-                            .attr("fill", line.color)
-                            .attr("x", w - margin_h)
-                            .attr("y", y(stats.mean))]);
-                        if(total_unit != null)
+                        });
+                    
+                    var text_boxes = [];
+                    for(var i = 0; i < lines.length; ++i) {
+                        var line = lines[i];
+                        var stats = get_area_mean(line.data);
+                        if(stats.mean != null) {
+                            var num = 0;
+                            var denom = 0;
+                            for(var j = 0; j < line.data.length; j++)
+                                if(line.data[j] != null) {
+                                    var d = line.data[j];
+                                    num += d.y*((d.y0 + d.y) + (d.y0))/2;
+                                    denom += d.y;
+                                }
+                            text_boxes.push([i, g.append("svg:text")
+                                .text(line.label + " (mean: " + d3.format(".3s")(stats.mean) + unit + ")")
+                                .attr("text-anchor", "start")
+                                .attr("dominant-baseline", "central")
+                                .attr("fill", line.color)
+                                .attr("x", w - margin_h + 10)
+                                .attr("y", y(num/denom))]);
+                        }
+                    }
+                } else {
+                    var y = d3.scale.linear().domain([
+                        0,
+                        d3.max(lines, function(line) { return d3.max(line.data, itemgetter(1)); } )
+                    ]).range([h - margin_v, margin_v]);
+                    
+                    g.selectAll().data(lines).enter().append("svg:path")
+                        .attr("d", function(line) {
+                            return d3.svg.line()
+                                .x(compose(x, as_date, itemgetter(0)))
+                                .y(compose(y, itemgetter(1)))
+                                .defined(compose(not_null, itemgetter(1)))
+                                (line.data)
+                        })
+                        .style("stroke", function(line) { return line.color })
+                        .attr("class", "plotline")
+                        .on("mouseover", function(line, i) {
+                            for(var j = 0; j < text_boxes.length; j++)
+                                text_boxes[j][1].attr("opacity", text_boxes[j][0] == i ? 1 : 0.3);
+                        });
+                    
+                    var text_boxes = [];
+                    for(var i = 0; i < lines.length; ++i) {
+                        var line = lines[i];
+                        var stats = get_area_mean(line.data);
+                        if(stats.mean != null) {
                             text_boxes.push([i, g.append("svg:text")
-                                .text("Area: " + d3.format(".3s")(stats.area) + total_unit)
+                                .text(line.label)
                                 .attr("text-anchor", "start")
                                 .attr("dominant-baseline", "central")
                                 .attr("fill", line.color)
                                 .attr("x", w - margin_h + 10)
-                                .attr("y", y(stats.mean) + 12)]);
+                                .attr("y", y(stats.mean) - 12)]);
+                            text_boxes.push([i, g.append("svg:text")
+                                .text("-Mean: " + d3.format(".3s")(stats.mean) + unit)
+                                .attr("text-anchor", "start")
+                                .attr("dominant-baseline", "central")
+                                .attr("fill", line.color)
+                                .attr("x", w - margin_h)
+                                .attr("y", y(stats.mean))]);
+                            if(total_unit != null)
+                                text_boxes.push([i, g.append("svg:text")
+                                    .text("Area: " + d3.format(".3s")(stats.area) + total_unit)
+                                    .attr("text-anchor", "start")
+                                    .attr("dominant-baseline", "central")
+                                    .attr("fill", line.color)
+                                    .attr("x", w - margin_h + 10)
+                                    .attr("y", y(stats.mean) + 12)]);
+                        }
                     }
                 }
                 
                     .attr("dominant-baseline", "central")
                     .attr("text-anchor", "middle");
             }
-            function plot_later(g, unit, total_unit, lines) { // takes lines with url attribute instead of data attribute
+            function plot_later(g, unit, total_unit, lines, stack) { // takes lines with url attribute instead of data attribute
                 var callbacks_left = lines.length;
                 lines.map(function(line) {
                     d3.json(line.url, function(line_data) {
                         line.data = line_data;
                         callbacks_left--;
                         if(callbacks_left == 0)
-                            plot(g, unit, total_unit, lines);
+                            plot(g, unit, total_unit, lines, stack);
                     });
                 });
             }
             
             function data_to_lines(data, sort_key) {
-                var vers = {}; for(var i = 0; i < data.length; ++i) if(data[i][1] != null) for(var v in data[i][1]) vers[v] = null;
+                var vers = {}; for(var i = 0; i < data.length; ++i) if(data[i][1] != null) for(var v in data[i][1]) if(data[i][1][v] != data[i][3]) vers[v] = null;
                 var verlist = []; for(var v in vers) verlist.push(v);
                 verlist.sort();
                 
                     {"url": "/web/graph_data/current_payout/last_" + lowerperiod, "color": "#0000FF"}
                 ]);
                 d3.json("/web/graph_data/pool_rates/last_" + lowerperiod, function(data) {
-                    plot(d3.select('#pool'), 'H/s', 'H', data_to_lines(data));
+                    plot(d3.select('#pool'), 'H/s', null, data_to_lines(data), true);
                 });
                 plot_later(d3.select("#peers"), "", null, [
                     {"url": "/web/graph_data/incoming_peers/last_" + lowerperiod, "color": "#0000FF", "label": "Incoming"},
                     {"url": "/web/graph_data/outgoing_peers/last_" + lowerperiod, "color": "#FF0000", "label": "Outgoing"}
-                ]);
+                ], true);
                 
                 d3.json("/web/graph_data/miner_hash_rates/last_" + lowerperiod, function(data) {
                     d3.json("/web/graph_data/miner_dead_hash_rates/last_" + lowerperiod, function(dead_data) {