Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Nov 30, 2011
2 parents 330f547 + a2f8431 commit 3588bbc
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 45 deletions.
43 changes: 27 additions & 16 deletions lib/cube/client/piece-area.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,28 @@ cube.piece.type.area = function(board) {

var time = div.append("div")
.attr("class", "time")
.text("Time Range:")
.append("select")
.on("change.area", area.edit)
.on("focus.area", area.focus)
.on("blur.area", area.blur);
.text("Time Range:");

time.selectAll("option")
time.append("input");

time.append("select").selectAll("option")
.data([
{description: "1 Day / 5-Minute", value: 864e5 + "/" + 3e5},
{description: "3 Days / 5-Minute", value: 3 * 864e5 + "/" + 3e5},
{description: "7 Days / Hour", value: 7 * 864e5 + "/" + 36e5},
{description: "14 Days / Hour", value: 14 * 864e5 + "/" + 36e5},
{description: "30 Days / Hour", value: 30 * 864e5 + "/" + 36e5},
{description: "30 Days / Day", value: 30 * 864e5 + "/" + 864e5}
{description: "Seconds @ 20", value: 2e4},
{description: "Minutes @ 5", value: 3e5},
{description: "Hours", value: 36e5},
{description: "Days", value: 864e5},
{description: "Weeks", value: 6048e5},
{description: "Months", value: 2592e6}
])
.enter().append("option")
.property("selected", function(d, i) { return i == 1; })
.attr("value", cube_piece_areaValue)
.text(function(d) { return d.description; });

time.selectAll("input,select")
.on("change.area", area.edit)
.on("focus.area", area.focus)
.on("blur.area", area.blur)
} else {
var m = [6, 40, 14, 10], // top, right, bottom, left margins
socket;
Expand Down Expand Up @@ -86,7 +89,7 @@ cube.piece.type.area = function(board) {
.style("height", innerSize[1] - 58 + "px");

transition.select(".time select")
.style("width", innerSize[0] - 100 + "px");
.style("width", innerSize[0] - 174 + "px");

} else {
var z = board.squareSize(),
Expand Down Expand Up @@ -147,16 +150,18 @@ cube.piece.type.area = function(board) {
}

function serialize(json) {
var t = time.property("value").split("/");
var step = +time.select("select").property("value"),
range = time.select("input").property("value") * cube_piece_areaMultipler(step);
json.type = "area";
json.query = query.property("value");
json.time = {range: +t[0], step: +t[1]};
json.time = {range: range, step: step};
}

function deserialize(json) {
if (mode == "edit") {
query.property("value", json.query);
time.property("value", json.time.range + "/" + json.time.step);
time.select("input").property("value", json.time.range / cube_piece_areaMultipler(json.time.step));
time.select("select").property("value", json.time.step);
} else {
var dt1 = json.time.step,
t1 = new Date(Math.floor(Date.now() / dt1) * dt1),
Expand Down Expand Up @@ -235,6 +240,12 @@ function cube_piece_areaValue(d) {

var cube_piece_formatNumber = d3.format(".2r");

function cube_piece_areaMultipler(step) {
return step / (step === 2e4 ? 20
: step === 3e5 ? 5
: 1);
}

function cube_piece_format(domain) {
var prefix = d3.formatPrefix(Math.max(-domain[0], domain[1]), 2);
return function(value) {
Expand Down
37 changes: 21 additions & 16 deletions lib/cube/client/piece-sum.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,28 @@ cube.piece.type.sum = function(board) {

var time = div.append("div")
.attr("class", "time")
.text("Time Range:")
.append("select")
.on("change.sum", sum.edit)
.on("focus.sum", sum.focus)
.on("blur.sum", sum.blur);
.text("Time Range:");

time.append("input");

time.selectAll("option")
time.append("select").selectAll("option")
.data([
{description: "5 Minutes / 5-Minute", value: 3e5 + "/" + 3e5},
{description: "1 Hour / 5-Minute", value: 36e5 + "/" + 3e5},
{description: "1 Hour / Hour", value: 36e5 + "/" + 36e5},
{description: "1 Day / 5-Minute", value: 864e5 + "/" + 3e5},
{description: "1 Day / Hour", value: 864e5 + "/" + 36e5},
{description: "1 Day / Day", value: 864e5 + "/" + 864e5}
{description: "Seconds @ 20", value: 2e4},
{description: "Minutes @ 5", value: 3e5},
{description: "Hours", value: 36e5},
{description: "Days", value: 864e5},
{description: "Weeks", value: 6048e5},
{description: "Months", value: 2592e6}
])
.enter().append("option")
.property("selected", function(d, i) { return i == 1; })
.attr("value", cube_piece_areaValue)
.text(function(d) { return d.description; });

time.selectAll("input,select")
.on("change.sum", sum.edit)
.on("focus.sum", sum.focus)
.on("blur.sum", sum.blur)
}

function resize() {
Expand All @@ -57,7 +60,7 @@ cube.piece.type.sum = function(board) {
.style("height", innerSize[1] - 58 + "px");

transition.select(".time select")
.style("width", innerSize[0] - 100 + "px");
.style("width", innerSize[0] - 174 + "px");
} else {
transition
.style("font-size", innerSize[0] / 5 + "px")
Expand All @@ -77,17 +80,19 @@ cube.piece.type.sum = function(board) {
}

function serialize(json) {
var t = time.property("value").split("/");
var step = +time.select("select").property("value"),
range = time.select("input").property("value") * cube_piece_areaMultipler(step);
json.type = "sum";
json.query = query.property("value");
json.time = {range: +t[0], step: +t[1]};
json.time = {range: range, step: step};
}

function deserialize(json) {
if (!json.time.range) json.time = {range: json.time, step: 3e5};
if (mode == "edit") {
query.property("value", json.query);
time.property("value", json.time.range + "/" + json.time.step);
time.select("input").property("value", json.time.range / cube_piece_areaMultipler(json.time.step));
time.select("select").property("value", json.time.step);
} else {
var dt = json.time.step,
t1 = new Date(Math.floor(Date.now() / dt) * dt),
Expand Down
7 changes: 6 additions & 1 deletion lib/cube/client/piece.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
margin: 4px;
}

.piece textarea {
.piece textarea, .piece input {
margin-left: 4px;
height: 20px;
border-radius: 4px;
Expand All @@ -43,6 +43,11 @@
line-height: 20px;
}

.piece input {
height: 16px;
width: 88px;
}

.piece select {
margin-right: 4px;
float: right;
Expand Down
9 changes: 4 additions & 5 deletions lib/cube/server/metric.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ exports.getter = function(db) {
// Request any needed fields.
expression.fields(fields);

find(start, stop, tier, callback);
find(start, stop, tier, reduce.pyramidal && tier.next, callback);

// The metric is computed recursively, reusing the above variables.
function find(start, stop, tier, callback) {
function find(start, stop, tier, pyramidal, callback) {
var compute = group ? (group.multi ? computeGroups : computeGroup)
: tier.next && reduce.pyramidal ? computePyramidal
: computeFlat;
: pyramidal ? computePyramidal : computeFlat;

// Query for the desired metric in the cache.
type.metrics.find({
Expand Down Expand Up @@ -165,7 +164,7 @@ exports.getter = function(db) {
// Group metrics from the next tier.
function computePyramidal(start, stop) {
var bins = {};
find(start, stop, tier.next, function(time, value) {
find(start, stop, tier.next, false, function(time, value) {
var bin = bins[time = tier.floor(time)] || (bins[time] = {size: tier.size(time), values: []});
if (bin.values.push(value) === bin.size) {
save(time, reduce(bin.values));
Expand Down
12 changes: 11 additions & 1 deletion lib/cube/server/tiers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var tiers = module.exports = {};

var second = 1000,
second20 = 20 * second,
minute = 60 * second,
minute5 = 5 * minute,
hour = 60 * minute,
Expand All @@ -9,11 +10,20 @@ var second = 1000,
month = 30 * day,
year = 365 * day;

tiers[second20] = {
key: second20,
floor: function(d) { return new Date(Math.floor(d / second20) * second20); },
ceil: tier_ceil,
step: function(d) { return new Date(+d + second20); }
};

tiers[minute5] = {
key: minute5,
floor: function(d) { return new Date(Math.floor(d / minute5) * minute5); },
ceil: tier_ceil,
step: function(d) { return new Date(+d + minute5); }
step: function(d) { return new Date(+d + minute5); },
next: tiers[second20],
size: function() { return 15; }
};

tiers[hour] = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cube",
"version": "0.0.13",
"version": "0.0.14",
"description": "A system for time series visualization using MongoDB, Node and D3.",
"keywords": ["time series", "visualization"],
"homepage": "http://square.github.com/cube/",
Expand Down
71 changes: 66 additions & 5 deletions test/tiers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ suite.addBatch({
keys.push(+key);
}
keys.sort(function(a, b) { return a - b; });
assert.deepEqual(keys, [3e5, 36e5, 864e5, 6048e5, 2592e6]);
assert.deepEqual(keys, [2e4, 3e5, 36e5, 864e5, 6048e5, 2592e6]);
}
},

"minute5": {
topic: tiers[3e5],
"has the key 3e5": function(tier) {
assert.strictEqual(tier.key, 3e5);
"second20": {
topic: tiers[2e4],
"has the key 2e4": function(tier) {
assert.strictEqual(tier.key, 2e4);
},
"next is undefined": function(tier) {
assert.isUndefined(tier.next);
Expand All @@ -29,6 +29,67 @@ suite.addBatch({
assert.isUndefined(tier.size);
},

"floor": {
"rounds down to 20-seconds": function(tier) {
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 00, 20)), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 00, 21)), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 00, 23)), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 00, 39)), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 00, 40)), utc(2011, 08, 02, 12, 00, 40));
},
"does not modify the passed-in date": function(tier) {
var date = utc(2011, 08, 02, 12, 00, 21);
assert.deepEqual(tier.floor(date), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(date, utc(2011, 08, 02, 12, 00, 21));
}
},

"ceil": {
"rounds up to 5-minutes": function(tier) {
assert.deepEqual(tier.ceil(utc(2011, 08, 02, 12, 00, 20)), utc(2011, 08, 02, 12, 00, 20));
assert.deepEqual(tier.ceil(utc(2011, 08, 02, 12, 00, 21)), utc(2011, 08, 02, 12, 00, 40));
assert.deepEqual(tier.ceil(utc(2011, 08, 02, 12, 00, 23)), utc(2011, 08, 02, 12, 00, 40));
assert.deepEqual(tier.ceil(utc(2011, 08, 02, 12, 00, 39)), utc(2011, 08, 02, 12, 00, 40));
assert.deepEqual(tier.ceil(utc(2011, 08, 02, 12, 00, 40)), utc(2011, 08, 02, 12, 00, 40));
},
"does not modified the specified date": function(tier) {
var date = utc(2011, 08, 02, 12, 00, 21);
assert.deepEqual(tier.ceil(date), utc(2011, 08, 02, 12, 00, 40));
assert.deepEqual(date, utc(2011, 08, 02, 12, 00, 21));
}
},

"step": {
"increments time by twenty minutes": function(tier) {
var date = utc(2011, 08, 02, 23, 59, 20);
assert.deepEqual(date = tier.step(date), utc(2011, 08, 02, 23, 59, 40));
assert.deepEqual(date = tier.step(date), utc(2011, 08, 03, 00, 00, 00));
assert.deepEqual(date = tier.step(date), utc(2011, 08, 03, 00, 00, 20));
assert.deepEqual(date = tier.step(date), utc(2011, 08, 03, 00, 00, 40));
assert.deepEqual(date = tier.step(date), utc(2011, 08, 03, 00, 01, 00));
},
"does not round the specified date": function(tier) {
assert.deepEqual(tier.step(utc(2011, 08, 02, 12, 21, 23)), utc(2011, 08, 02, 12, 21, 43));
},
"does not modify the specified date": function(tier) {
var date = utc(2011, 08, 02, 12, 20, 00);
assert.deepEqual(tier.step(date), utc(2011, 08, 02, 12, 20, 20));
assert.deepEqual(date, utc(2011, 08, 02, 12, 20, 00));
}
}
},
"minute5": {
topic: tiers[3e5],
"has the key 3e5": function(tier) {
assert.strictEqual(tier.key, 3e5);
},
"next is the 20-second tier": function(tier) {
assert.equal(tier.next, tiers[2e4]);
},
"size is 15": function(tier) {
assert.strictEqual(tier.size(), 15);
},

"floor": {
"rounds down to 5-minutes": function(tier) {
assert.deepEqual(tier.floor(utc(2011, 08, 02, 12, 20, 00)), utc(2011, 08, 02, 12, 20));
Expand Down

0 comments on commit 3588bbc

Please sign in to comment.