From f3f6febb24acbaa71994ccac8b853e9a5346cb9d Mon Sep 17 00:00:00 2001 From: Mircea Danila Dumitrescu Date: Mon, 19 May 2014 16:28:18 +0100 Subject: [PATCH] Refactoring frontend js --- bin/generator-config.js | 4 +- lib/analytics/genericGetter.js | 10 +- public/js/analytics.js | 1301 ++++++++++++++------------------ 3 files changed, 593 insertions(+), 722 deletions(-) diff --git a/bin/generator-config.js b/bin/generator-config.js index bd330ec..be36e9f 100644 --- a/bin/generator-config.js +++ b/bin/generator-config.js @@ -1,11 +1,11 @@ module.exports = { - "packetsInInterval": 2000000, + "packetsInInterval": 100000, "intervalInMS": 60000, "sampleRateInMS": 100, "data": { "country": ["US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "GB", "IN", "IN", "IN", "IN", "IN", "IN", "FR", "FR", "FR", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "JP", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "GA", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW"], "device": ["web", "iphone", "android"], "gender": ["male", "male", "male", "female", "female", "female", "female", "female", "female", "female"], - "type": ["t1","t2","t2","t2","t2","t2","t2","t3","t3","t3","t3","t3","t3","t3","t3","t3","t3"] + "type": ["t1"] } }; \ No newline at end of file diff --git a/lib/analytics/genericGetter.js b/lib/analytics/genericGetter.js index 4068caf..6f4cfb8 100644 --- a/lib/analytics/genericGetter.js +++ b/lib/analytics/genericGetter.js @@ -2,7 +2,8 @@ var myutils = require("./myutils.js"), mongodb = require("mongodb"), type_re = /^[a-z][a-zA-Z0-9_]+$/, - MAX_RETURNED_RECORDS = 10000; + MAX_RETURNED_RECORDS = 10000, + util = require("util"); function customQuery(collectionObj, filter, sort, limit, batchSize, streamified, documentHandler) { // set MongoDB cursor options var cursorOptions = {}, @@ -28,8 +29,7 @@ function customQuery(collectionObj, filter, sort, limit, batchSize, streamified, if (streamified) { stream = cursor.sort({$natural: -1}).stream(); stream.on('data', function (document) { - document.time = document.t; - document.data = (document.d === undefined ? document.key : document.d); + document.d = (document.d === undefined ? document.key : document.d); documentHandler(document); }); } @@ -52,7 +52,8 @@ function customQuery(collectionObj, filter, sort, limit, batchSize, streamified, // A null name indicates that there are no more results. if (document) { - documentHandler({id: document._id, time: document.t, data: (document.d === undefined ? document.key : document.d)}); + document.d = (document.d === undefined ? document.key : document.d); + documentHandler(document); } else { documentHandler(null); @@ -160,6 +161,7 @@ module.exports = function (db) { if (document) { streams.active.forEach(function (documentHandler) { if (!documentHandler.closed) { + console.log("document handled: " + util.inspect(document, {colors: true, depth: null})); documentHandler(document); } }); diff --git a/public/js/analytics.js b/public/js/analytics.js index b1af0ad..56862f6 100644 --- a/public/js/analytics.js +++ b/public/js/analytics.js @@ -5,766 +5,635 @@ /*global createElem*/ /*global WebSocket*/ /*global crossfilter*/ +/*global window*/ -/** - * create a real time instance for events line chart. - * To make it work, an HTML element with a specific ID needs to be added in the HTML file. - * var rt = new RealTimeEvents(); - * rt.setChartAnchor('#line-chart'); - * rt.init(); - */ -function RealTimeEvents() { - var _this = this; - - /** - * add chart object - * @param callback - */ - this.addCharts = function (callback) { - nv.addGraph(function () { - _this.chart - .showLegend(false) - .margin({top: 10, bottom: 30, left: 60, right: 60}) - .useInteractiveGuideline(true) - ; - - _this.chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the partent chart, so need to chain separately - .tickFormat(function (d) { - return d3.time.format('%X')(new Date(d)); - }); - - _this.chart.yAxis - .tickFormat(function (d) { - return d3.format('d')(d); - }) - .axisLabel('Count') - ; - return _this.chart; - }); - - if (callback) { - callback(); - } - }; - - /** - * refresh chart - * @param callback - */ - this.refreshChart = function (callback) { - d3.select(_this.chartAnchor + ' svg') +var realTimeEvents = { + refreshChart: function (callback) { + d3.select(this.chartAnchor + ' svg') .datum([ { key: 'Events', - values: _this.chartData + values: this.chartData } ]) - .transition().duration(1) - .call(_this.chart); + .transition().duration(800) + .call(this.chart); //Figure out a good way to do this automatically - nv.utils.windowResize(_this.chart.update); + nv.utils.windowResize(this.chart.update); if (callback) { callback(); } - }; - - /** - * refresh chartData - * @param callback - */ - this.refreshChartData = function (callback) { - var timer = _this.timer, - t, - x, - y; - _this.chartData = []; - for (t = timer.min; t < timer.now; t += 1e3) { - x = new Date(t); - y = _this._data[t] || 0; - _this.chartData.push({ - x: x, - y: y - }); + }, + dataHandler: function (eventData) { + var t, + i, + lastTime; + + if (eventData) { + t = eventData.t; + } else { + t = (new Date()).getTime(); } - - if (callback) { - callback(); + t = t - t % 1e3; + + //get the last timestamp + if (this.chartData.length === 0) { + //add the first element + lastTime = (new Date()).getTime(); + lastTime = lastTime - lastTime % 1e3; + this.chartData.push({x: new Date(lastTime), y: 0}); + } else { + lastTime = this.chartData[this.chartData.length - 1].x.getTime(); } - }; - /** - * handle incoming event data - * @param eventData - */ - this.dataHandler = function (eventData) { - var t = eventData.time - eventData.time % 1e3; - if (_this._data[t] === undefined) { - _this._data[t] = 0; - } - _this._data[t]++; - }; - - /** - * reset data - */ - this.resetData = function (callback) { - var i; - for (i in _this._data) { - if (_this._data.hasOwnProperty(i)) { - if (Number(i) < _this.timer.min) { - delete _this._data[i]; - } + if (lastTime < t) { + // console.log("add zeroes as necessary then insert t: " + t); + for (i = lastTime + 1e3; i < t; i += 1e3) { + this.chartData.push({x: new Date(i), y: 0}); } - } - if (callback) { - callback(); - } - }; - - /** - * update timer - * @param [callback] - */ - this.updateTimer = function (callback) { - var timer = _this.timer; - timer.nowReal = new Date().getTime(); - timer.now = timer.nowReal - timer.nowReal % 1e3; - timer.min = timer.now - timer.timePeriod; // start of chart - timer.max = timer.now - timer.now % 1e3; - if (callback) { - callback(); - } - }; - - /** - * refresh all - */ - this.refreshAll = function () { - _this.refreshChartData(function () { - if (_this.chartData && _this.chartData.length) { - _this.refreshChart(function () { - _this.resetData(); - }); + if (eventData) { + this.chartData.push({x: new Date(t), y: 1}); } - _this.updateTimer(); - }); - }; - - /** - * init HTML - */ - this.initHtml = function (callback) { - if ($(_this.chartAnchor + ' svg').length === 0) { // create svg - $(_this.chartAnchor) - .append(createElem('div', {className: 'control'})) // for control buttons - .append('') // svg for chart - ; - } - - $(_this.chartAnchor + ' .control') - .append(createElem('span', {className: 'title'}, 'Events')) // title - .append(createElem('button', {className: 'pause'}, 'Pause')) // pause button - .append(createElem('button', {className: 'resume'}, 'Resume')) // resume - ; - - $(_this.chartAnchor + ' button.pause') - .click(function () { - _this.pause(); - }) - ; - $(_this.chartAnchor + ' button.resume') - .click(function () { - _this.resume(); - }) - ; - - if (callback) { - callback(); - } - }; - - /** - * major init - */ - this.init = function () { - _this.initSocket(function () { - _this.initHtml(function () { - _this.addCharts(function () { - setTimeout(function () { - _this.intervalHandle = setInterval(function () { - _this.refreshAll(); - }, _this.refreshFrequency); - }, 1e3); - }); - }); - }); - }; - - /** - * initialize socket - * @param [callback] - */ - this.initSocket = function (callback) { - if (_this.socket !== null) { - _this.resetData(function () { - _this._data = {}; - _this.chartData = []; - }); - } - _this.socket = new WebSocket(_this.socketConnection); - _this.socket.onopen = function () { - console.log("connected to " + _this.socketConnection); - _this.socket.send(JSON.stringify(_this.socketPacket)); - }; - _this.socket.onmessage = function (message) { - var event; - if (message) { - if (message.data) { - event = JSON.parse(message.data); - if (event && event.data) { - _this.dataHandler(event); - } + else { + this.chartData.push({x: new Date(t), y: 0}); + } + } else if (lastTime === t) { + // console.log("lastTime is t: " + t); + if (eventData) { + this.chartData[this.chartData.length - 1].y++; + } + } else if (lastTime > t) { + //console.log("go back and look for the correct record to increment, but don,t go back too much t: " + t); + for (i = this.chartData.length - 2; i > ((this.chartData.length - 7) > 0 ? this.chartData.length - 7 : 0); i--) { + if (this.chartData[i].x.getTime() === t) { + this.chartData[i].y++; + break; } } - }; - _this.socket.onclose = function () { - console.log("closed"); - }; - _this.socket.onerror = function (error) { - console.log("error", error); - }; - if (callback) { - callback(); } - }; - - /** - * set eventType - * @param eventType - */ - this.setEventType = function (eventType) { - _this.eventType = eventType; - console.log('eventType is set to ' + _this.eventType); - }; - /** - * set chart html anchor - * @param chartAnchor - */ - this.setChartAnchor = function (chartAnchor) { - if (!chartAnchor.match('^#.*')) { - chartAnchor = '#' + chartAnchor; + while (this.chartData.length > 60) { + this.chartData.shift(); } - _this.chartAnchor = chartAnchor; - console.log('chartAnchor is set to ' + _this.chartAnchor); - }; - - /** - * set timePeriod - * @param timePeriod - * @param [callback] - */ - this.setTimePeriod = function (timePeriod, callback) { - _this.timer.timePeriod = timePeriod; - _this._updateSocketPacket(); - console.log('timePeriod is set to ' + _this.timer.timePeriod); - if (callback) { - callback(); + }, + refreshAll: function () { + //this.refreshChartData(function () { + this.dataHandler(); + if (this.chartData && this.chartData.length) { + this.refreshChart(); } - }; - - this._updateSocketPacket = function () { - _this.socketPacket = { - type: _this.eventType, - start: new Date(new Date().getTime() - _this.timer.timePeriod) - }; - }; - - /** - * set socketConnection - * @param value - */ - this.setSocketConnection = function (value) { - _this.socketConnection = value; - }; - - /** - * set socketPacket - * @param value - */ - this.setSocketPacket = function (value) { - _this.socketPacket = value; - }; - /** - * set timePeriod - * @param value - */ - this.setsampleDuration = function (value) { - _this.timer.timePeriod = value; - }; - - /** - * pause refresh data - */ - this.pause = function () { - clearInterval(_this.intervalHandle); - }; - - /** - * resume - */ - this.resume = function () { - setTimeout(function () { - _this.intervalHandle = setInterval(function () { - _this.refreshAll(); - }, _this.refreshFrequency); - }, 1e3); - }; - - /** - * test - */ - this.test = function () { - _this.setEventType('t1'); - _this.setChartAnchor('line-chart'); - _this.init(); - }; - - // variables - this.eventType = 't1'; // event type - this.chartAnchor = ''; - this.chartData = []; // chartData should be formatted like {x: new Date, y: 130}... - this._data = {}; // temporary data dictionary for aggregation - this.timer = { - timePeriod: 60 * 1e3, // 60 seconds - now: null, - nowReal: null, - min: null, - max: null - }; - this.refreshFrequency = 1e3; - this.chart = nv.models.lineChart(); - this.socket = null; - this.socketConnection = 'ws://localhost:1081/1.0/event/get'; - this.socketPacket = { - type: _this.eventType, - start: new Date(new Date().getTime() - _this.timer.timePeriod) - }; - this.intervalHandle = null; -} - -/** - * create a real time instance for aggregation stack chart. - * @type {RealTimeEvents} - */ -function RealTimeAggregations() { - var _this = this; + }, + init: function () { + var that = this, + initSocket = function (callback) { + that.socket = new WebSocket(that.socketConnection); + that.socket.onopen = function () { + console.log("connected to " + that.socketConnection); + that.socket.send(JSON.stringify(that.socketPacket())); + }; + that.socket.onmessage = function (message) { + var event; + if (message) { + if (message.data) { + event = JSON.parse(message.data); + if (event && event.d) { + that.dataHandler(event); + } + } + } + }; + that.socket.onclose = function () { + console.log("closed"); + }; + that.socket.onerror = function (error) { + console.log("error", error); + }; + if (callback) { + callback(); + } + }, + initHtml = function (callback) { + if ($(that.chartAnchor + ' svg').length === 0) { // create svg + $(that.chartAnchor) + .append(createElem('div', {className: 'control'})) // for control buttons + .append('') // svg for chart + ; + } - /** - * add chart objects - * @param callback - */ - this.addCharts = function (callback) { - _this.dimTargetKeys.forEach(function (dimTargetKey) { - var chart = nv.models.stackedAreaChart(); - nv.addGraph(function () { - chart - .showLegend(false) - .margin({top: 10, bottom: 30, left: 60, right: 60}) - .useInteractiveGuideline(true) + $(that.chartAnchor + ' .control') + .append(createElem('span', {className: 'title'}, 'Events')) // title + .append(createElem('button', {className: 'pause'}, 'Pause')) // pause button + .append(createElem('button', {className: 'resume'}, 'Resume')) // resume ; - chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the partent chart, so need to chain separately - .tickFormat(function (d) { - return d3.time.format('%X')(new Date(d)); - }); - - chart.yAxis - .tickFormat(function (d) { - return d3.format('d')(d); + $(that.chartAnchor + ' button.pause') + .click(function () { + that.pause(); }) - .axisLabel('Count') ; - return chart; - }); - - _this.charts[dimTargetKey] = chart; - }); - - if (callback) { - callback(); - } - }; - - /** - * refresh chart - * @param callback - */ - this.refreshChart = function (callback) { - _this.dimTargetKeys.forEach(function (dimTargetKey) { - var chartId = _this.chartAnchor.replaceAll('#') + '-' + dimTargetKey.replaceAll('.', '-'), - chart = _this.charts[dimTargetKey], - chartData = _this.chartDataList[dimTargetKey]; - d3.select('#' + chartId + ' svg') - .datum(chartData) - .transition().duration(1) - .call(chart); - }); - - //Figure out a good way to do this automatically - //nv.utils.windowResize(_this.chart.update); - - if (callback) { - callback(); - } - }; - - /** - * refresh chartData - * @param callback - */ - this.refreshChartData = function (callback) { - _this.chartDataList = {}; - var ndx = crossfilter(_this._data), - dimTime = ndx.dimension(function (d) { - return new Date(d.time); - }); - // console.log(grpDimTime.all());//debug - _this.dimTargetKeys.forEach(function (dimTargetKey) { - var chartData = [], // store all data series for a stack chart - dimTarget = ndx.dimension(function (d) { - return d[dimTargetKey]; - }), - dimTargetValsUniq = _this._data.ix(dimTargetKey).unique(); - dimTargetValsUniq.forEach(function (v) { - var t, - tmp = {}, - values, - x, - y; - dimTarget.filter(v); - values = dimTime.group().reduceSum(function (d) { - return d.count; - }).all(); // store values for one series in a stack chart - values.forEach(function (d) { - tmp[d.key.getTime()] = d.value; - }); - values = []; - for (t = _this.timer.min; t < _this.timer.now; t += _this.resolution) { - x = new Date(t); - y = tmp[t] || 0; - values.push({ - x: x, - y: y + $(that.chartAnchor + ' button.resume') + .click(function () { + that.resume(); }); + if (callback) { + callback(); } - chartData.push({ - key: v, - values: values + }, + addCharts = function (callback) { + nv.addGraph(function () { + that.chart + .showLegend(false) + .margin({top: 10, bottom: 30, left: 60, right: 60}) + .useInteractiveGuideline(true) + ; + + that.chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the partent chart, so need to chain separately + .tickFormat(function (d) { + return d3.time.format('%X')(new Date(d)); + }); + + that.chart.yAxis + .tickFormat(function (d) { + return d3.format('d')(d); + }) + .axisLabel('Count') + ; + return that.chart; }); - }); - dimTarget.filter(null); - _this.chartDataList[dimTargetKey] = chartData; - }); - if (callback) { - callback(); - } - }; - - /** - * handle incoming event data - * @param aggregationData - */ - this.dataHandler = function (aggregationData) { -// console.log(JSON.flatten(aggregationData));//debug - _this._data.push(JSON.flatten(aggregationData)); - }; - - /** - * reset data - */ - this.resetData = function (callback) { - var tmp = []; - _this._data.forEach(function (d) { - if (d.time >= _this.timer.min) { - tmp.push(d); - } - }); - _this._data = tmp; - if (callback) { - callback(); - } - }; - - /** - * update timer - * @param [callback] - */ - this.updateTimer = function (callback) { - var timer = _this.timer; - timer.nowReal = new Date().getTime(); - timer.now = timer.nowReal - timer.nowReal % _this.resolution; - timer.min = (timer.now - timer.timePeriod) - (timer.now - timer.timePeriod) % _this.resolution; - timer.max = timer.now - timer.now % _this.resolution; - if (callback) { - callback(); - } - }; - - /** - * refresh all - */ - this.refreshAll = function () { - _this.refreshChartData(function () { - _this.refreshChart(function () { - _this.resetData(); - }); - _this.updateTimer(); - }); - }; - - /** - * init HTML - */ - this.initHtml = function (callback) { - var $tmp = $('
'), - $anchor = $(_this.chartAnchor), - $control = $(createElem('div', {className: 'control'})), // elements in control block - selectorLookup = { - 'data.v1': ['male', 'female', 'all'], - 'data.v2': ['web', 'android', 'web', 'all'], - 'data.v3': ['GB', 'US', 'IN', 'JP', 'all'] - };// control block TODO: add listeners to control stack area - _this.dimTargetKeys.forEach(function (dimTargetKey) { - var selectorId = _this.chartAnchor.replaceAll('#') + '-selector-' + dimTargetKey.replaceAll('.', '-'), - $selector = $(createElem('select', {id: selectorId})); - $selector.append(''); // default option - selectorLookup[dimTargetKey].forEach(function (option) { - $selector.append(createElem('option', {'value': option}, option)); - }); - $control - .append($tmp.clone().append($selector).html()) - ; - }); - $anchor - .append($tmp.clone().append($control).html()) - ; - _this.dimTargetKeys.forEach(function (dimTargetKey) { - var chartId = _this.chartAnchor.replaceAll('#') + '-' + dimTargetKey.replaceAll('.', '-'), - $elem = createElem('div', {id: chartId}); - $($elem) - .append(createElem('svg')) - ; - $anchor - .append($tmp.clone().append($elem).html()) - ; - }); - - if (callback) { - callback(); - } - }; - - /** - * major init - */ - this.init = function () { - _this.initSocket(function () { - _this.initHtml(function () { - _this.addCharts(function () { - setTimeout(function () { - _this.intervalHandle = setInterval(function () { - _this.refreshAll(); - }, _this.refreshFrequency); // refresh frequency - }, 2e3); // initial waiting time + if (callback) { + callback(); + } + }; + initSocket(function () { + initHtml(function () { + addCharts(function () { + that.intervalHandle = setInterval( + function () { + that.refreshAll(); + }, + that.refreshFrequency); }); }); }); - }; - - /** - * initialize socket - * @param [callback] - */ - this.initSocket = function (callback) { - if (_this.socket !== null || _this.socket !== undefined) { - _this.resetData(function () { - _this._data = []; - _this.chartData = []; - }); - } - _this.socket = new WebSocket(_this.socketConnection); - _this.socket.onopen = function () { - console.log("connected to " + _this.socketConnection); - _this.socket.send(JSON.stringify(_this.socketPacket)); - }; - _this.socket.onmessage = function (message) { - var jsonData; - if (message) { - if (message.data) { - jsonData = JSON.parse(message.data); - if (jsonData && jsonData.data) { - _this.dataHandler(jsonData); - } - } - } - }; - _this.socket.onclose = function () { - console.log("closed"); - }; - _this.socket.onerror = function (error) { - console.log("error", error); - }; - if (callback) { - callback(); - } - }; - - /** - * init listeners - * @param [callback] - */ - this.initListners = function (callback) { - console.log("Not implemented yet"); - if (callback) { - callback(); - } - }; - - /** - * set eventType - * @param value - */ - this.setAggType = function (value) { - _this.aggType = value; - console.log('aggType is set to ' + _this.aggType); - }; - - /** - * set chart html anchor - * @param chartAnchor - */ - this.setChartAnchor = function (chartAnchor) { + }, + setEventType: function (eventType) { + this.eventType = eventType; + console.log('eventType is set to ' + this.eventType); + }, + setChartAnchor: function (chartAnchor) { if (!chartAnchor.match('^#.*')) { chartAnchor = '#' + chartAnchor; } - _this.chartAnchor = chartAnchor; - console.log('chartAnchor is set to ' + _this.chartAnchor); - }; - - /** - * set timePeriod - * @param timePeriod - * @param [callback] - */ - this.setTimePeriod = function (timePeriod, callback) { - _this.timer.timePeriod = timePeriod; - _this._updateSocketPacket(); - console.log('timePeriod is set to ' + _this.timer.timePeriod); - if (callback) { - callback(); - } - }; - - this._updateSocketPacket = function () { - _this.socketPacket = { - name: _this.aggType, - start: new Date(new Date().getTime() - _this.timer.timePeriod) - }; - }; - - /** - * set socketConnection - * @param value - */ - this.setSocketConnection = function (value) { - _this.socketConnection = value; - }; - - /** - * set socketPacket - * @param value - */ - this.setSocketPacket = function (value) { - _this.socketPacket = value; - }; - /** - * set timePeriod - * @param value - */ - this.setsampleDuration = function (value) { - _this.timer.timePeriod = value; - }; - - /** - * pause refresh data - */ - this.pause = function () { - clearInterval(_this.intervalHandle); - }; - - /** - * resume - */ - this.resume = function () { + this.chartAnchor = chartAnchor; + console.log('chartAnchor is set to ' + this.chartAnchor); + }, + pause: function () { + clearInterval(this.intervalHandle); + }, + resume: function () { setTimeout(function () { - _this.intervalHandle = setInterval(function () { - _this.refreshAll(); - }, _this.refreshFrequency); + this.intervalHandle = setInterval(function () { + this.refreshAll(); + }, this.refreshFrequency); }, 1e3); - }; - - /** - * test - */ - this.test = function () { - _this.setAggType('t1'); - _this.setChartAnchor('stack-charts'); - _this.init(); - }; - - // variables - this.aggType = 'agg1'; - this.chartAnchor = ''; - this.chartDataList = {}; - this._data = []; // temporary data dictionary for aggregation - this.timer = { - timePeriod: 60 * 60 * 1e3, // 60 minutes + }, + start: function (eventType) { + this.setEventType(eventType); + this.setChartAnchor("line-chart"); + this.init(); + }, + socketConnection: 'ws://localhost:1081/1.0/event/get', + eventType: 't1', // default event type + chartAnchor: '', + chartData: [], // chartData should be formatted like {x: new Date, y: 130}... + timer: { + timePeriod: 60 * 1e3, // 60 seconds now: null, nowReal: null, min: null, max: null - }; - this.resolutionLookup = { - '1m': 60 * 1e3, - '5m': 5 * 60 * 1e3, - '1h': 60 * 60 * 1e3 - }; - this.resolutionName = '1m'; - this.resolution = this.resolutionLookup[this.resolutionName]; - this.refreshFrequency = 5 * 1e3; // refresh every 5 seconds, will be deprecated - this.dimTargetKeys = [ - 'data.v1', - 'data.v2', - 'data.v3' - ]; - this.charts = {}; - this.socket = null; - this.socketConnection = 'ws://localhost:1081/1.0/aggregation/get'; - this.socketPacket = { - name: _this.aggType + '_' + _this.resolutionName, - start: new Date(new Date().getTime() - _this.timer.timePeriod) - }; - this.intervalHandle = null; -} + }, + refreshFrequency: 1e3, + chart: nv.models.lineChart(), + socket: null, + socketPacket: function () { + return { + type: this.eventType, + start: new Date(new Date().getTime() - this.timer.timePeriod) + }; + }, + intervalHandle: 0 +}; + +/** + * create a real time instance for aggregation stack chart. + * @type {RealTimeEvents} + */ + //function RealTimeAggregations() { + // var this = this; + // + // /** + // * add chart objects + // * @param callback + // */ + // this.addCharts = function (callback) { + // this.dimTargetKeys.forEach(function (dimTargetKey) { + // var chart = nv.models.stackedAreaChart(); + // nv.addGraph(function () { + // chart + // .showLegend(false) + // .margin({top: 10, bottom: 30, left: 60, right: 60}) + // .useInteractiveGuideline(true) + // ; + // + // chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the partent chart, so need to chain separately + // .tickFormat(function (d) { + // return d3.time.format('%X')(new Date(d)); + // }); + // + // chart.yAxis + // .tickFormat(function (d) { + // return d3.format('d')(d); + // }) + // .axisLabel('Count') + // ; + // return chart; + // }); + // + // this.charts[dimTargetKey] = chart; + // }); + // + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * refresh chart + // * @param callback + // */ + // this.refreshChart = function (callback) { + // this.dimTargetKeys.forEach(function (dimTargetKey) { + // var chartId = this.chartAnchor.replaceAll('#') + '-' + dimTargetKey.replaceAll('.', '-'), + // chart = this.charts[dimTargetKey], + // chartData = this.chartDataList[dimTargetKey]; + // d3.select('#' + chartId + ' svg') + // .datum(chartData) + // .transition().duration(1) + // .call(chart); + // }); + // + // //Figure out a good way to do this automatically + // //nv.utils.windowResize(this.chart.update); + // + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * refresh chartData + // * @param callback + // */ + // this.refreshChartData = function (callback) { + // this.chartDataList = {}; + // var ndx = crossfilter(this._data), + // dimTime = ndx.dimension(function (d) { + // return new Date(d.time); + // }); + // // console.log(grpDimTime.all());//debug + // this.dimTargetKeys.forEach(function (dimTargetKey) { + // var chartData = [], // store all data series for a stack chart + // dimTarget = ndx.dimension(function (d) { + // return d[dimTargetKey]; + // }), + // dimTargetValsUniq = this._data.ix(dimTargetKey).unique(); + // dimTargetValsUniq.forEach(function (v) { + // var t, + // tmp = {}, + // values, + // x, + // y; + // dimTarget.filter(v); + // values = dimTime.group().reduceSum(function (d) { + // return d.count; + // }).all(); // store values for one series in a stack chart + // values.forEach(function (d) { + // tmp[d.key.getTime()] = d.value; + // }); + // values = []; + // for (t = this.timer.min; t < this.timer.now; t += this.resolution) { + // x = new Date(t); + // y = tmp[t] || 0; + // values.push({ + // x: x, + // y: y + // }); + // } + // chartData.push({ + // key: v, + // values: values + // }); + // }); + // dimTarget.filter(null); + // this.chartDataList[dimTargetKey] = chartData; + // }); + // + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * handle incoming event data + // * @param aggregationData + // */ + // this.dataHandler = function (aggregationData) { + // // console.log(JSON.flatten(aggregationData));//debug + // this._data.push(JSON.flatten(aggregationData)); + // }; + // + // /** + // * reset data + // */ + // this.resetData = function (callback) { + // var tmp = []; + // this._data.forEach(function (d) { + // if (d.time >= this.timer.min) { + // tmp.push(d); + // } + // }); + // this._data = tmp; + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * update timer + // * @param [callback] + // */ + // this.updateTimer = function (callback) { + // var timer = this.timer; + // timer.nowReal = new Date().getTime(); + // timer.now = timer.nowReal - timer.nowReal % this.resolution; + // timer.min = (timer.now - timer.timePeriod) - (timer.now - timer.timePeriod) % this.resolution; + // timer.max = timer.now - timer.now % this.resolution; + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * refresh all + // */ + // this.refreshAll = function () { + // this.refreshChartData(function () { + // this.refreshChart(function () { + // this.resetData(); + // }); + // this.updateTimer(); + // }); + // }; + // + // /** + // * init HTML + // */ + // this.initHtml = function (callback) { + // var $tmp = $('
'), + // $anchor = $(this.chartAnchor), + // $control = $(createElem('div', {className: 'control'})), // elements in control block + // selectorLookup = { + // 'data.v1': ['male', 'female', 'all'], + // 'data.v2': ['web', 'android', 'web', 'all'], + // 'data.v3': ['GB', 'US', 'IN', 'JP', 'all'] + // };// control block TODO: add listeners to control stack area + // this.dimTargetKeys.forEach(function (dimTargetKey) { + // var selectorId = this.chartAnchor.replaceAll('#') + '-selector-' + dimTargetKey.replaceAll('.', '-'), + // $selector = $(createElem('select', {id: selectorId})); + // $selector.append(''); // default option + // selectorLookup[dimTargetKey].forEach(function (option) { + // $selector.append(createElem('option', {'value': option}, option)); + // }); + // $control + // .append($tmp.clone().append($selector).html()) + // ; + // }); + // $anchor + // .append($tmp.clone().append($control).html()) + // ; + // this.dimTargetKeys.forEach(function (dimTargetKey) { + // var chartId = this.chartAnchor.replaceAll('#') + '-' + dimTargetKey.replaceAll('.', '-'), + // $elem = createElem('div', {id: chartId}); + // $($elem) + // .append(createElem('svg')) + // ; + // $anchor + // .append($tmp.clone().append($elem).html()) + // ; + // }); + // + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * major init + // */ + // this.init = function () { + // this.initSocket(function () { + // this.initHtml(function () { + // this.addCharts(function () { + // setTimeout(function () { + // this.intervalHandle = setInterval(function () { + // this.refreshAll(); + // }, this.refreshFrequency); // refresh frequency + // }, 2e3); // initial waiting time + // }); + // }); + // }); + // }; + // + // /** + // * initialize socket + // * @param [callback] + // */ + // this.initSocket = function (callback) { + // if (this.socket !== null || this.socket !== undefined) { + // this.resetData(function () { + // this._data = []; + // this.chartData = []; + // }); + // } + // this.socket = new WebSocket(this.socketConnection); + // this.socket.onopen = function () { + // console.log("connected to " + this.socketConnection); + // this.socket.send(JSON.stringify(this.socketPacket)); + // }; + // this.socket.onmessage = function (message) { + // var jsonData; + // if (message) { + // if (message.data) { + // jsonData = JSON.parse(message.data); + // if (jsonData && jsonData.data) { + // this.dataHandler(jsonData); + // } + // } + // } + // }; + // this.socket.onclose = function () { + // console.log("closed"); + // }; + // this.socket.onerror = function (error) { + // console.log("error", error); + // }; + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * init listeners + // * @param [callback] + // */ + // this.initListners = function (callback) { + // console.log("Not implemented yet"); + // if (callback) { + // callback(); + // } + // }; + // + // /** + // * set eventType + // * @param value + // */ + // this.setAggType = function (value) { + // this.aggType = value; + // console.log('aggType is set to ' + this.aggType); + // }; + // + // /** + // * set chart html anchor + // * @param chartAnchor + // */ + // this.setChartAnchor = function (chartAnchor) { + // if (!chartAnchor.match('^#.*')) { + // chartAnchor = '#' + chartAnchor; + // } + // this.chartAnchor = chartAnchor; + // console.log('chartAnchor is set to ' + this.chartAnchor); + // }; + // + // /** + // * set timePeriod + // * @param timePeriod + // * @param [callback] + // */ + // this.setTimePeriod = function (timePeriod, callback) { + // this.timer.timePeriod = timePeriod; + // this._updateSocketPacket(); + // console.log('timePeriod is set to ' + this.timer.timePeriod); + // if (callback) { + // callback(); + // } + // }; + // + // this._updateSocketPacket = function () { + // this.socketPacket = { + // name: this.aggType, + // start: new Date(new Date().getTime() - this.timer.timePeriod) + // }; + // }; + // + // /** + // * set socketConnection + // * @param value + // */ + // this.setSocketConnection = function (value) { + // this.socketConnection = value; + // }; + // + // /** + // * set socketPacket + // * @param value + // */ + // this.setSocketPacket = function (value) { + // this.socketPacket = value; + // }; + // /** + // * set timePeriod + // * @param value + // */ + // this.setsampleDuration = function (value) { + // this.timer.timePeriod = value; + // }; + // + // /** + // * pause refresh data + // */ + // this.pause = function () { + // clearInterval(this.intervalHandle); + // }; + // + // /** + // * resume + // */ + // this.resume = function () { + // setTimeout(function () { + // this.intervalHandle = setInterval(function () { + // this.refreshAll(); + // }, this.refreshFrequency); + // }, 1e3); + // }; + // + // /** + // * test + // */ + // this.test = function () { + // this.setAggType('t1'); + // this.setChartAnchor('stack-charts'); + // this.init(); + // }; + // + // // variables + // this.aggType = 'agg1'; + // this.chartAnchor = ''; + // this.chartDataList = {}; + // this._data = []; // temporary data dictionary for aggregation + // this.timer = { + // timePeriod: 60 * 60 * 1e3, // 60 minutes + // now: null, + // nowReal: null, + // min: null, + // max: null + // }; + // this.resolutionLookup = { + // '1m': 60 * 1e3, + // '5m': 5 * 60 * 1e3, + // '1h': 60 * 60 * 1e3 + // }; + // this.resolutionName = '1m'; + // this.resolution = this.resolutionLookup[this.resolutionName]; + // this.refreshFrequency = 5 * 1e3; // refresh every 5 seconds, will be deprecated + // this.dimTargetKeys = [ + // 'data.v1', + // 'data.v2', + // 'data.v3' + // ]; + // this.charts = {}; + // this.socket = null; + // this.socketConnection = 'ws://localhost:1081/1.0/aggregation/get'; + // this.socketPacket = { + // name: this.aggType + '_' + this.resolutionName, + // start: new Date(new Date().getTime() - this.timer.timePeriod) + // }; + // this.intervalHandle = null; + //} function testRealTime() { - var rte = new RealTimeEvents(); -//, - window.rta = new RealTimeAggregations(); - rte.test(); - rta.test(); + realTimeEvents.start("t1"); } \ No newline at end of file