Skip to content

Commit

Permalink
add bucketize
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewjstone committed Oct 26, 2011
1 parent 437991e commit 8b9b77b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 29 deletions.
16 changes: 12 additions & 4 deletions README.md
Expand Up @@ -56,13 +56,21 @@ config attributes:

## methods

#### chart.addBar(size, color);
Add a bar at the next position, which is 'chart.step' spaces away on the axis perpendicular to 'chart.direction'.
#### chart.addBar(size, color)
Manually add a bar at the next position, which is 'chart.step' spaces away on the axis perpendicular to 'chart.direction'.

* size - size of the bar in nominal units
* size - Size of the bar in nominal units
* color - Ansi color string - 'white','red','blue', etc...

#### chart.draw();

### chart.bucketize(data, min, max)
Instead of manually adding bars with addBar() you can just add your data and allow cli-chart to automatically put data in buckets based on the minimum and maximum size of the data. The number of buckets is equal to the width or height(based on direction) of the chart in characters divided by the step size. Data is sorted from min to max when bucketized. Size is automatically scaled to fit the bars in the graph and label the axis of the chart direction.

* data - An array of values to chart
* min - The minimum value of this data in nominal units
* max - The maximum value of this data in nominal units

#### chart.draw()
Draw the chart consisting of the bars created with chart.addBar().


Expand Down
4 changes: 2 additions & 2 deletions bar.js
Expand Up @@ -8,11 +8,11 @@ var Bar = module.exports = function(chart, size, color) {
this.color = color || defaults.color;
};

Bar.prototype.draw = function() {
Bar.prototype.draw = function(scale) {
var charm = this.chart.charm;
var dir = this.chart.direction;
charm.background(this.color);
for (var i = 0; i < this.size; i++) {
for (var i = 0; i < Math.round(this.size*scale); i++) {
if (dir === 'x') {
charm.write(' ');
} else {
Expand Down
69 changes: 46 additions & 23 deletions chart.js
Expand Up @@ -11,8 +11,6 @@ var defaults = {
xmin: 0,
ymin: 0
};
defaults.xmax = defaults.width;
defaults.ymax = defaults.height;

var Chart = module.exports = function(config) {
var charm = this.charm = config.charm;
Expand All @@ -29,24 +27,42 @@ var Chart = module.exports = function(config) {
this.step = config.step || defaults.step;
this.bars = [];
this.xmin = config.xmin || defaults.xmin;
this.xmax = config.xmax || defaults.xmax;
this.xmax = config.xmax || this.width;
this.ymin = config.ymin || defaults.ymin;
this.ymax = config.ymax || defaults.ymax;
this.yscale = 1;
this.xscale = 1;
this.ymax = config.ymax || this.height;
this.max_size = 0;
};

if (this.ymin || this.ymax != defaults.height) {
this.yscale = this.height/(this.ymax - this.ymin);
// min and max here must be in the same units as data. This is different from
// xmin, xmax, ymin, ymax in that those are for labels and may be in different units.
Chart.prototype.bucketize = function(data, min, max) {
var numBuckets = 0;
if (this.direction === 'x') {
numBuckets = Math.floor(this.height/this.step);
} else {
numBuckets = Math.floor(this.width/this.step);
}

if (this.xmin || this.xmax != defaults.width) {
this.xscale = this.width/(this.xmax - this.xmin);
var bucketWidth = (max - min)/numBuckets;
data.sort(function(a, b) {
return a - b;
});
var size = 0;
var bucket_ct = 0;
var max_size = 0;
for (var i = 0; i < data.length; i++) {
if (data[i] > min+bucketWidth*(bucket_ct+1)) {
this.addBar(size);
bucket_ct++;
size = 0;
}
size++;
}
this.addBar(size);
};

Chart.prototype.addBar = function(size, color) {
var scale = this.direction === 'y' ? this.yscale : this.xscale;
this.bars.push(new Bar(this, Math.round(size*scale), color));
if (size > this.max_size) this.max_size = size;
this.bars.push(new Bar(this, size, color));
return this;
};

Expand All @@ -65,14 +81,14 @@ Chart.prototype.drawAxes = function() {
charm.write('\n\n');
charm.up(2);
charm.right(this.lmargin+1);

// The cursor is now at the origin of the graph
// The cursor is now at the origin of the graph

// draw x axis
charm.push();

charm.write('\n');
charm.right(this.lmargin);
for (i = this.lmargin-1; i < this.width; i++) {
for (i = this.lmargin-1; i < this.width+this.lmargin-1; i++) {
charm.write('-');
}
charm.pop();
Expand All @@ -95,7 +111,7 @@ Chart.prototype.labelAxes = function() {
charm.up(this.height/2);

// move to the top of the y axis
var ymaxstr = String(this.ymax);
var ymaxstr = this.direction === 'y' ? String(this.max_size) : String(this.ymax);
charm.left(ymaxstr.length);
charm.write(ymaxstr);
charm.pop();
Expand All @@ -107,17 +123,24 @@ Chart.prototype.labelAxes = function() {
charm.write('\n\n');
charm.right(this.lmargin+1);
charm.write(String(this.xmin));
charm.left(this.lmargin+1);
charm.right(this.width/2);
charm.right(this.width/2 - String(this.xmin).length);
charm.write(this.xlabel);
charm.right(this.width/2-this.lmargin);
charm.write(String(this.xmax));
charm.right(this.width/2 - this.xlabel.length);
var xmaxstr = this.direction === 'x' ? String(this.max_size) : String(this.xmax);
charm.write(xmaxstr);
charm.pop();

}
};

Chart.prototype.drawBars = function() {
// set scale based on max_size
if (this.direction === 'x') {
this.scale = this.width/this.max_size;
} else {
this.scale = this.height/this.max_size;
}

var charm = this.charm;
for (var i = 0; i < this.bars.length; i++) {
if (this.direction === 'x') {
Expand All @@ -126,7 +149,7 @@ Chart.prototype.drawBars = function() {
if (i != 0) charm.right(this.step);
}
charm.push();
this.bars[i].draw();
this.bars[i].draw(this.scale);
charm.pop();
}
if (this.direction === 'x') charm.down(this.step*this.bars.length+1);
Expand All @@ -138,5 +161,5 @@ Chart.prototype.draw = function() {
this.drawAxes();
this.labelAxes();
this.drawBars();
this.charm.write('\n\n');
this.charm.write('\n\n');
};
17 changes: 17 additions & 0 deletions test/chart_vertical_bucketize_test.js
@@ -0,0 +1,17 @@
var Chart = require('../chart');

var chart = new Chart({width: 120, height: 20, directon: 'y', xlabel: 'time (hrs)',
ylabel: 'winners', xmax: 3});

var min = new Date().getTime();
var max = new Date(min+1000*60*60*3); // 3 hrs
var data = [];
for (var i = 0; i < 1000; i++) {
var date = Math.floor(min + Math.random()*(max - min));
data.push(date);
}

chart.bucketize(data, min, max);
chart.draw();
process.exit();

0 comments on commit 8b9b77b

Please sign in to comment.