mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Modularized panels
This commit is contained in:
parent
59503c5e22
commit
b3052d0c95
BIN
common/.DS_Store
vendored
BIN
common/.DS_Store
vendored
Binary file not shown.
@ -8,4 +8,8 @@
|
||||
|
||||
#upload {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
[ng\:cloak], [ng-cloak], .ng-cloak {
|
||||
display: none !important;
|
||||
}
|
BIN
common/lib/.DS_Store
vendored
BIN
common/lib/.DS_Store
vendored
Binary file not shown.
5
common/lib/LAB.min.js
vendored
Normal file
5
common/lib/LAB.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
config.js
10
config.js
@ -8,6 +8,9 @@ refresh: Milliseconds between auto refresh.
|
||||
timeformat: Format for time in histograms (might go away)
|
||||
timefield: Field to use for ISO8601 timestamps (might go away)
|
||||
indexpattern: Timestamping pattern for time based indices,
|
||||
modules: Panel modules to load. In the future these will be inferred
|
||||
from your initial dashboard, though if you share dashboards you
|
||||
will probably need to list them all here
|
||||
|
||||
NOTE: No timezone support yet, everything is in UTC at the moment.
|
||||
|
||||
@ -17,8 +20,6 @@ shared.json contains an example sharable dashboard. Note the subtle differences
|
||||
between dashboard.js and shared.json. Once is a javascript object, the other is
|
||||
json.
|
||||
|
||||
PLEASE SEE js/
|
||||
|
||||
*/
|
||||
var config = new Settings(
|
||||
{
|
||||
@ -29,8 +30,7 @@ var config = new Settings(
|
||||
timefield: '@timestamp',
|
||||
//indexpattern: '"logstash-"yyyy.mm.dd',
|
||||
indexpattern: '"shakespeare"',
|
||||
modules: ['histogram','piequery','pieterms','stackedquery','map'],
|
||||
|
||||
modules: ['histogram','pieterms','piequery','stackedquery','map'],
|
||||
|
||||
defaultfields: ['line_text'],
|
||||
perpage: 50,
|
||||
@ -42,4 +42,4 @@ var config = new Settings(
|
||||
indexdefault: 'logstash-*',
|
||||
primaryfield: '_all'
|
||||
}
|
||||
);
|
||||
);
|
||||
|
31
index.html
31
index.html
@ -17,44 +17,17 @@
|
||||
<link rel="stylesheet" href="/common/css/bootstrap-responsive.min.css">
|
||||
<link rel="stylesheet" href="/common/css/elasticjs.css">
|
||||
<link rel="stylesheet" href="/common/css/datepicker.css">
|
||||
<link rel="stylesheet" href="/common/css/jquery-jvectormap.css">
|
||||
|
||||
|
||||
<!-- project dependency libs -->
|
||||
<script src="common/lib/jquery-1.8.0.min.js"></script>
|
||||
<script src="common/lib/modernizr-2.6.1.min.js"></script>
|
||||
<script src="/common/lib/LAB.min.js"></script>
|
||||
<script src="common/lib/underscore.min.js"></script>
|
||||
<script src="common/lib/angular.min.js"></script>
|
||||
<script src="common/lib/elastic.min.js"></script>
|
||||
<script src="common/lib/elastic-angular-client.min.js"></script>
|
||||
<script src="common/lib/dateformat.js"></script>
|
||||
<script src="common/lib/jquery.flot.js"></script>
|
||||
<script src="common/lib/jquery.flot.time.js"></script>
|
||||
<script src="common/lib/jquery.flot.stack.js"></script>
|
||||
<script src="common/lib/jquery.flot.pie.js"></script>
|
||||
<script src="common/lib/jquery.jvectormap.min.js"></script>
|
||||
<script src="common/lib/jquery-jvectormap-world-mill-en.js"></script>
|
||||
<script src="common/lib/date.js"></script>
|
||||
<script src="common/lib/datepicker.js"></script>
|
||||
|
||||
|
||||
<script src="common/lib/settings.js"></script>
|
||||
<script src="config.js"></script>
|
||||
<script src="common/lib/shared.js"></script>
|
||||
<script src="dashboards.js"></script>
|
||||
|
||||
|
||||
<!-- project specific files -->
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/services.js"></script>
|
||||
<script src="js/controllers.js"></script>
|
||||
<script src="js/filters.js"></script>
|
||||
<script src="js/directives.js"></script>
|
||||
<script src="js/panels.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body ng-controller="DashCtrl">
|
||||
<body ng-controller="DashCtrl" ng-cloak>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container-fluid">
|
||||
|
46
js/app.js
46
js/app.js
@ -12,13 +12,41 @@ var modules = [
|
||||
'kibana.panels',
|
||||
]
|
||||
|
||||
var scripts = []
|
||||
|
||||
var labjs = $LAB
|
||||
.script("common/lib/jquery-1.8.0.min.js").wait()
|
||||
.script("common/lib/modernizr-2.6.1.min.js")
|
||||
.script("common/lib/underscore.min.js")
|
||||
.script("common/lib/angular.min.js")
|
||||
.script("common/lib/elastic.min.js")
|
||||
.script("common/lib/elastic-angular-client.min.js")
|
||||
.script("common/lib/dateformat.js")
|
||||
.script("common/lib/date.js")
|
||||
.script("common/lib/datepicker.js")
|
||||
.script("common/lib/shared.js")
|
||||
.script("js/services.js")
|
||||
.script("js/controllers.js")
|
||||
.script("js/filters.js")
|
||||
.script("js/directives.js")
|
||||
.script("js/panels.js")
|
||||
.script("dashboards.js");
|
||||
|
||||
_.each(config.modules, function(v) {
|
||||
labjs = labjs.script('js/panels/'+v+'/module.js').wait()
|
||||
modules.push('kibana.'+v)
|
||||
})
|
||||
|
||||
/* Application level module which depends on filters, controllers, and services */
|
||||
angular.module('kibana', modules).config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/dashboard', {
|
||||
templateUrl: 'partials/dashboard.html'
|
||||
})
|
||||
.otherwise({
|
||||
redirectTo: '/dashboard'
|
||||
});
|
||||
}]);
|
||||
labjs.wait(function(){
|
||||
angular.module('kibana', modules).config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/dashboard', {
|
||||
templateUrl: 'partials/dashboard.html'
|
||||
})
|
||||
.otherwise({
|
||||
redirectTo: '/dashboard'
|
||||
});
|
||||
}]);
|
||||
|
||||
});
|
||||
|
@ -12,7 +12,7 @@ angular.module('kibana.directives', [])
|
||||
return (attrs.panel && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
if (ready) {
|
||||
$compile("<div "+attrs.panel+" params={{panel}} style='height:{{row.height}}'></div>")(scope).replaceAll(element);
|
||||
element.html($compile("<div "+attrs.panel+" params={{panel}} style='height:{{row.height}}'></div>")(scope))
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -23,7 +23,6 @@ angular.module('kibana.directives', [])
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
console.log(elem);
|
||||
function file_selected(evt) {
|
||||
var files = evt.target.files; // FileList object
|
||||
|
||||
|
714
js/panels.js
714
js/panels.js
@ -71,718 +71,4 @@
|
||||
of queries in your queries array
|
||||
show: array of what to show, (eg ['bars','lines','points'])
|
||||
*/
|
||||
|
||||
|
||||
angular.module('kibana.panels', [])
|
||||
.directive('histogram', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
query : "*",
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
color : "#27508C",
|
||||
show : ['bars']
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
if (_.isUndefined(attrs.params.interval))
|
||||
scope.params.interval = secondsToHms(
|
||||
calculate_interval(scope.from,scope.to,50,0)/1000),
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.DateHistogramFacet('histogram')
|
||||
.field(config.timefield)
|
||||
.interval(params.interval)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets.histogram.entries;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Determine format
|
||||
var show = _.isUndefined(params.show) ? {
|
||||
bars: true, lines: false, points: false
|
||||
} : {
|
||||
lines: _.indexOf(params.show,'lines') < 0 ? false : true,
|
||||
bars: _.indexOf(params.show,'bars') < 0 ? false : true,
|
||||
points: _.indexOf(params.show,'points') < 0 ? false : true,
|
||||
}
|
||||
|
||||
// Push null values at beginning and end of timeframe
|
||||
scope.graph = [
|
||||
[scope.from.getTime(), null],[scope.to.getTime(), null]];
|
||||
|
||||
// Create FLOT value array
|
||||
_.each(scope.data, function(v, k) {
|
||||
scope.graph.push([v['time'],v['count']])
|
||||
});
|
||||
|
||||
// Set barwidth based on specified interval
|
||||
var barwidth = interval_to_seconds(params.interval)*1000
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, [{
|
||||
label: _.isUndefined(params.label) ? params.query: params.label,
|
||||
data: scope.graph
|
||||
}], {
|
||||
legend: {
|
||||
position: "nw",
|
||||
labelFormatter: function(label, series) {
|
||||
return '<span class="legend">' + label + ' / ' + params.interval
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
series: {
|
||||
lines: { show: show.lines, fill: false },
|
||||
bars: { show: show.bars, fill: 1, barWidth: barwidth/1.8 },
|
||||
points: { show: show.points },
|
||||
color: params.color,
|
||||
shadowSize: 1
|
||||
},
|
||||
yaxis: { min: 0, color: "#000" },
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
timeformat: "%H:%M:%S<br>%m-%d",
|
||||
label: "Datetime",
|
||||
color: "#000",
|
||||
},
|
||||
grid: {
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 0,
|
||||
borderColor: '#eee',
|
||||
color: "#eee",
|
||||
hoverable: true,
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('pieterms', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
size : 5,
|
||||
query : "*",
|
||||
exclude : [],
|
||||
donut : false,
|
||||
tilt : false,
|
||||
legend : true,
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.TermsFacet('termpie')
|
||||
.field(params.field)
|
||||
.size(params['size'])
|
||||
.exclude(params.exclude)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets.termpie.terms;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Create graph array
|
||||
scope.graph = [];
|
||||
_.each(scope.data, function(v, k) {
|
||||
if(!_.isUndefined(params.only) && _.indexOf(params.only,v['term']) < 0)
|
||||
return
|
||||
|
||||
var point = {
|
||||
label : v['term'],
|
||||
data : v['count']
|
||||
}
|
||||
|
||||
if(!_.isUndefined(params.colors))
|
||||
point.color = params.colors[_.indexOf(params.only,v['term'])]
|
||||
|
||||
scope.graph.push(point)
|
||||
});
|
||||
|
||||
var pie = {
|
||||
series: {
|
||||
pie: {
|
||||
innerRadius: params.donut ? 0.4 : 0,
|
||||
tilt: params.tilt ? 0.45 : 1,
|
||||
radius: 1,
|
||||
show: true,
|
||||
combine: {
|
||||
color: '#999',
|
||||
label: 'The Rest'
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
radius: 2/3,
|
||||
formatter: function(label, series){
|
||||
return '<div style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
|
||||
label+'<br/>'+Math.round(series.percent)+'%</div>';
|
||||
},
|
||||
threshold: 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
//grid: { hoverable: true, clickable: true },
|
||||
legend: { show: params.legend }
|
||||
};
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, pie);
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('piequery', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
donut : false,
|
||||
tilt : false,
|
||||
legend : true,
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
|
||||
var queries = [];
|
||||
// Build the question part of the query
|
||||
_.each(params.queries, function(v) {
|
||||
queries.push(ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(v || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false))
|
||||
)
|
||||
});
|
||||
|
||||
_.each(queries, function(v) {
|
||||
request = request.facet(ejs.QueryFacet(_.indexOf(queries,v))
|
||||
.query(v)
|
||||
.facetFilter(ejs.QueryFilter(v))
|
||||
)
|
||||
})
|
||||
// Then the insert into facet and make the request
|
||||
var results = request.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Create graph array
|
||||
scope.graph = [];
|
||||
_.each(scope.data, function(v, k) {
|
||||
var point = {
|
||||
label : params.queries[k],
|
||||
data : v['count']
|
||||
}
|
||||
if(!_.isUndefined(params.colors))
|
||||
point.color = params.colors[k%params.colors.length];
|
||||
scope.graph.push(point)
|
||||
});
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, {
|
||||
series: {
|
||||
pie: {
|
||||
innerRadius: params.donut ? 0.4 : 0,
|
||||
tilt: params.tilt ? 0.45 : 1,
|
||||
radius: 1,
|
||||
show: true,
|
||||
combine: {
|
||||
color: '#999',
|
||||
label: 'The Rest'
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
radius: 2/3,
|
||||
formatter: function(label, series){
|
||||
return '<div style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
|
||||
label+'<br/>'+Math.round(series.percent)+'%</div>';
|
||||
},
|
||||
threshold: 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
//grid: { hoverable: true, clickable: true },
|
||||
legend: { show: params.legend }
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('stackedquery', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
colors : ["#BF3030","#1D7373","#86B32D","#A98A21","#411F73"],
|
||||
show : ['bars']
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
if (_.isUndefined(attrs.params.interval))
|
||||
scope.params.interval = secondsToHms(
|
||||
calculate_interval(scope.from,scope.to,50,0)/1000),
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var queries = [];
|
||||
_.each(params.queries, function(v) {
|
||||
queries.push(ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(v || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false))
|
||||
)
|
||||
});
|
||||
|
||||
// Build the facet part
|
||||
_.each(queries, function(v) {
|
||||
request = request
|
||||
.facet(ejs.DateHistogramFacet(_.indexOf(queries,v))
|
||||
.field(config.timefield)
|
||||
.interval(params.interval)
|
||||
.facetFilter(ejs.QueryFilter(v))
|
||||
)
|
||||
})
|
||||
|
||||
// Then run it
|
||||
var results = request.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Determine format
|
||||
var show = _.isUndefined(params.show) ? {
|
||||
bars: true, lines: false, points: false, fill: false
|
||||
} : {
|
||||
lines: _.indexOf(params.show,'lines') < 0 ? false : true,
|
||||
bars: _.indexOf(params.show,'bars') < 0 ? false : true,
|
||||
points: _.indexOf(params.show,'points') < 0 ? false : true,
|
||||
fill: _.indexOf(params.show,'fill') < 0 ? false : true
|
||||
}
|
||||
|
||||
scope.graph = [];
|
||||
// Push null values at beginning and end of timeframe
|
||||
_.each(scope.data, function(v, k) {
|
||||
var series = {};
|
||||
var data = [[scope.from.getTime(), null]];
|
||||
_.each(v.entries, function(v, k) {
|
||||
data.push([v['time'],v['count']])
|
||||
});
|
||||
data.push([scope.to.getTime(), null])
|
||||
series.data = {
|
||||
label: params.queries[k],
|
||||
data: data,
|
||||
color: params.colors[k%params.colors.length]
|
||||
};
|
||||
scope.graph.push(series.data)
|
||||
});
|
||||
|
||||
// Set barwidth based on specified interval
|
||||
var barwidth = interval_to_seconds(params.interval)*1000
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, {
|
||||
legend: {
|
||||
position: "nw",
|
||||
labelFormatter: function(label, series) {
|
||||
return '<span class="legend">' + label + ' / ' + params.interval
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
series: {
|
||||
stack: 0,
|
||||
lines: { show: show.lines, fill: show.fill },
|
||||
bars: { show: show.bars, fill: 1, barWidth: barwidth/1.8 },
|
||||
points: { show: show.points },
|
||||
color: params.color,
|
||||
shadowSize: 1
|
||||
},
|
||||
yaxis: { min: 0, color: "#000" },
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
timeformat: "%H:%M:%S<br>%m-%d",
|
||||
label: "Datetime",
|
||||
color: "#000",
|
||||
},
|
||||
grid: {
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 0,
|
||||
borderColor: '#eee',
|
||||
color: "#eee",
|
||||
hoverable: true,
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('map', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
colors : ["#BF3030","#1D7373","#86B32D","#A98A21","#411F73"],
|
||||
show : ['bars'],
|
||||
size : 100,
|
||||
exclude : []
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
if (_.isUndefined(attrs.params.interval))
|
||||
scope.params.interval = secondsToHms(
|
||||
calculate_interval(scope.from,scope.to,50,0)/1000),
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.TermsFacet('worldmap')
|
||||
.field(params.field)
|
||||
.size(params['size'])
|
||||
.exclude(params.exclude)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets.worldmap.terms;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Determine format
|
||||
var show = _.isUndefined(params.show) ? {
|
||||
bars: true, lines: false, points: false, fill: false
|
||||
} : {
|
||||
lines: _.indexOf(params.show,'lines') < 0 ? false : true,
|
||||
bars: _.indexOf(params.show,'bars') < 0 ? false : true,
|
||||
points: _.indexOf(params.show,'points') < 0 ? false : true,
|
||||
fill: _.indexOf(params.show,'fill') < 0 ? false : true
|
||||
}
|
||||
|
||||
scope.graph = [];
|
||||
// Push null values at beginning and end of timeframe
|
||||
_.each(scope.data, function(v, k) {
|
||||
var series = {};
|
||||
var data = [[scope.from.getTime(), null]];
|
||||
_.each(v.entries, function(v, k) {
|
||||
data.push([v['time'],v['count']])
|
||||
});
|
||||
data.push([scope.to.getTime(), null])
|
||||
series.data = {
|
||||
label: params.queries[k],
|
||||
data: data,
|
||||
color: params.colors[k%params.colors.length]
|
||||
};
|
||||
scope.graph.push(series.data)
|
||||
});
|
||||
|
||||
// Set barwidth based on specified interval
|
||||
var barwidth = interval_to_seconds(params.interval)*1000
|
||||
var values = {}
|
||||
_.each(scope.data, function(v) {
|
||||
values[v.term.toUpperCase()] = v.count;
|
||||
});
|
||||
console.log(values)
|
||||
|
||||
// Populate element
|
||||
$('.jvectormap-label,.jvectormap-zoomin,.jvectormap-zoomout').remove();
|
||||
elem.text('');
|
||||
elem.vectorMap({
|
||||
map: 'world_mill_en',
|
||||
regionStyle: {initial: {fill: '#eee'}},
|
||||
zoomOnScroll: false,
|
||||
backgroundColor: '#fff',
|
||||
series: {
|
||||
regions: [{
|
||||
values: values,
|
||||
scale: ['#C8EEFF', '#0071A4'],
|
||||
normalizeFunction: 'polynomial'
|
||||
}]
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
150
js/panels/histogram/module.js
Normal file
150
js/panels/histogram/module.js
Normal file
@ -0,0 +1,150 @@
|
||||
labjs = labjs.script("common/lib/jquery.flot.js")
|
||||
.script("common/lib/jquery.flot.time.js")
|
||||
|
||||
angular.module('kibana.histogram', [])
|
||||
.directive('histogram', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
query : "*",
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
color : "#27508C",
|
||||
show : ['bars']
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
if (_.isUndefined(attrs.params.interval))
|
||||
scope.params.interval = secondsToHms(
|
||||
calculate_interval(scope.from,scope.to,50,0)/1000),
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
if(scope.ready)
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.DateHistogramFacet('histogram')
|
||||
.field(config.timefield)
|
||||
.interval(params.interval)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets.histogram.entries;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Determine format
|
||||
var show = _.isUndefined(params.show) ? {
|
||||
bars: true, lines: false, points: false
|
||||
} : {
|
||||
lines: _.indexOf(params.show,'lines') < 0 ? false : true,
|
||||
bars: _.indexOf(params.show,'bars') < 0 ? false : true,
|
||||
points: _.indexOf(params.show,'points') < 0 ? false : true,
|
||||
}
|
||||
|
||||
// Push null values at beginning and end of timeframe
|
||||
scope.graph = [
|
||||
[scope.from.getTime(), null],[scope.to.getTime(), null]];
|
||||
|
||||
// Create FLOT value array
|
||||
_.each(scope.data, function(v, k) {
|
||||
scope.graph.push([v['time'],v['count']])
|
||||
});
|
||||
|
||||
// Set barwidth based on specified interval
|
||||
var barwidth = interval_to_seconds(params.interval)*1000
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, [{
|
||||
label: _.isUndefined(params.label) ? params.query: params.label,
|
||||
data: scope.graph
|
||||
}], {
|
||||
legend: {
|
||||
position: "nw",
|
||||
labelFormatter: function(label, series) {
|
||||
return '<span class="legend">' + label + ' / ' + params.interval
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
series: {
|
||||
lines: { show: show.lines, fill: false },
|
||||
bars: { show: show.bars, fill: 1, barWidth: barwidth/1.8 },
|
||||
points: { show: show.points },
|
||||
color: params.color,
|
||||
shadowSize: 1
|
||||
},
|
||||
yaxis: { min: 0, color: "#000" },
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
timeformat: "%H:%M:%S<br>%m-%d",
|
||||
label: "Datetime",
|
||||
color: "#000",
|
||||
},
|
||||
grid: {
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 0,
|
||||
borderColor: '#eee',
|
||||
color: "#eee",
|
||||
hoverable: true,
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
114
js/panels/map/module.js
Normal file
114
js/panels/map/module.js
Normal file
@ -0,0 +1,114 @@
|
||||
labjs = labjs.script("common/lib/jquery.jvectormap.min.js")
|
||||
.script("common/lib/jquery-jvectormap-world-mill-en.js")
|
||||
|
||||
angular.module('kibana.map', [])
|
||||
.directive('map', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
colors : ["#BF3030","#1D7373","#86B32D","#A98A21","#411F73"],
|
||||
show : ['bars'],
|
||||
size : 100,
|
||||
exclude : []
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending panel if data changes
|
||||
scope.$watch('data', function() {
|
||||
if(scope.ready)
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the window is resized
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.TermsFacet('worldmap')
|
||||
.field(params.field)
|
||||
.size(params['size'])
|
||||
.exclude(params.exclude)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = {};
|
||||
_.each(results.facets.worldmap.terms, function(v) {
|
||||
scope.data[v.term.toUpperCase()] = v.count;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Populate element
|
||||
$('.jvectormap-label,.jvectormap-zoomin,.jvectormap-zoomout').remove();
|
||||
elem.text('');
|
||||
elem.vectorMap({
|
||||
map: 'world_mill_en',
|
||||
regionStyle: {initial: {fill: '#ddd'}},
|
||||
zoomOnScroll: false,
|
||||
backgroundColor: '#fff',
|
||||
series: {
|
||||
regions: [{
|
||||
values: scope.data,
|
||||
scale: ['#C8EEFF', '#0071A4'],
|
||||
normalizeFunction: 'polynomial'
|
||||
}]
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
134
js/panels/piequery/module.js
Normal file
134
js/panels/piequery/module.js
Normal file
@ -0,0 +1,134 @@
|
||||
labjs = labjs.script("common/lib/jquery.flot.js")
|
||||
.script("common/lib/jquery.flot.pie.js")
|
||||
|
||||
angular.module('kibana.piequery', [])
|
||||
.directive('piequery', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
donut : false,
|
||||
tilt : false,
|
||||
legend : true,
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
if(scope.ready)
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
|
||||
var queries = [];
|
||||
// Build the question part of the query
|
||||
_.each(params.queries, function(v) {
|
||||
queries.push(ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(v || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false))
|
||||
)
|
||||
});
|
||||
|
||||
_.each(queries, function(v) {
|
||||
request = request.facet(ejs.QueryFacet(_.indexOf(queries,v))
|
||||
.query(v)
|
||||
.facetFilter(ejs.QueryFilter(v))
|
||||
)
|
||||
})
|
||||
// Then the insert into facet and make the request
|
||||
var results = request.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Create graph array
|
||||
scope.graph = [];
|
||||
_.each(scope.data, function(v, k) {
|
||||
var point = {
|
||||
label : params.queries[k],
|
||||
data : v['count']
|
||||
}
|
||||
if(!_.isUndefined(params.colors))
|
||||
point.color = params.colors[k%params.colors.length];
|
||||
scope.graph.push(point)
|
||||
});
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, {
|
||||
series: {
|
||||
pie: {
|
||||
innerRadius: params.donut ? 0.4 : 0,
|
||||
tilt: params.tilt ? 0.45 : 1,
|
||||
radius: 1,
|
||||
show: true,
|
||||
combine: {
|
||||
color: '#999',
|
||||
label: 'The Rest'
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
radius: 2/3,
|
||||
formatter: function(label, series){
|
||||
return '<div style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
|
||||
label+'<br/>'+Math.round(series.percent)+'%</div>';
|
||||
},
|
||||
threshold: 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
//grid: { hoverable: true, clickable: true },
|
||||
legend: { show: params.legend }
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
140
js/panels/pieterms/module.js
Normal file
140
js/panels/pieterms/module.js
Normal file
@ -0,0 +1,140 @@
|
||||
labjs = labjs.script("common/lib/jquery.flot.js")
|
||||
.script("common/lib/jquery.flot.pie.js")
|
||||
|
||||
angular.module('kibana.pieterms', [])
|
||||
.directive('pieterms', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
size : 5,
|
||||
query : "*",
|
||||
exclude : [],
|
||||
donut : false,
|
||||
tilt : false,
|
||||
legend : true,
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
if(scope.ready)
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var query = ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(params.query || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false)
|
||||
);
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var results = request
|
||||
.facet(ejs.TermsFacet('termpie')
|
||||
.field(params.field)
|
||||
.size(params['size'])
|
||||
.exclude(params.exclude)
|
||||
.facetFilter(ejs.QueryFilter(query))
|
||||
)
|
||||
.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets.termpie.terms;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Create graph array
|
||||
scope.graph = [];
|
||||
_.each(scope.data, function(v, k) {
|
||||
if(!_.isUndefined(params.only) && _.indexOf(params.only,v['term']) < 0)
|
||||
return
|
||||
|
||||
var point = {
|
||||
label : v['term'],
|
||||
data : v['count']
|
||||
}
|
||||
|
||||
if(!_.isUndefined(params.colors))
|
||||
point.color = params.colors[_.indexOf(params.only,v['term'])]
|
||||
|
||||
scope.graph.push(point)
|
||||
});
|
||||
|
||||
var pie = {
|
||||
series: {
|
||||
pie: {
|
||||
innerRadius: params.donut ? 0.4 : 0,
|
||||
tilt: params.tilt ? 0.45 : 1,
|
||||
radius: 1,
|
||||
show: true,
|
||||
combine: {
|
||||
color: '#999',
|
||||
label: 'The Rest'
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
radius: 2/3,
|
||||
formatter: function(label, series){
|
||||
return '<div style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
|
||||
label+'<br/>'+Math.round(series.percent)+'%</div>';
|
||||
},
|
||||
threshold: 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
//grid: { hoverable: true, clickable: true },
|
||||
legend: { show: params.legend }
|
||||
};
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, pie);
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
165
js/panels/stackedquery/module.js
Normal file
165
js/panels/stackedquery/module.js
Normal file
@ -0,0 +1,165 @@
|
||||
labjs = labjs.script("common/lib/jquery.flot.js")
|
||||
.script("common/lib/jquery.flot.time.js")
|
||||
.script("common/lib/jquery.flot.stack.js")
|
||||
|
||||
angular.module('kibana.stackedquery', [])
|
||||
.directive('stackedquery', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
|
||||
// Specify defaults for ALL directives
|
||||
var _d = {
|
||||
queries : ["*"],
|
||||
interval: secondsToHms(calculate_interval(scope.from,scope.to,40,0)/1000),
|
||||
colors : ["#BF3030","#1D7373","#86B32D","#A98A21","#411F73"],
|
||||
show : ['bars']
|
||||
}
|
||||
|
||||
// Set ready flag and fill parameters (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function () {
|
||||
return (attrs.params && scope.index) ? true : false;
|
||||
}, function (ready) {
|
||||
scope.ready = ready;
|
||||
if(ready) {
|
||||
scope.params = JSON.parse(attrs.params);
|
||||
_.each(_d, function(v, k) {
|
||||
scope.params[k] = _.isUndefined(scope.params[k])
|
||||
? _d[k] : scope.params[k];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also get the data if time frame changes.
|
||||
// (REQUIRED IN EVERY PANEL)
|
||||
scope.$watch(function() {
|
||||
return angular.toJson([scope.from, scope.to, scope.ready])
|
||||
}, function(){
|
||||
if(scope.ready)
|
||||
if (_.isUndefined(attrs.params.interval))
|
||||
scope.params.interval = secondsToHms(
|
||||
calculate_interval(scope.from,scope.to,50,0)/1000),
|
||||
get_data(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Re-rending the panel if it is resized,
|
||||
scope.$watch('data', function() {
|
||||
if(scope.ready)
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Or if the model changes
|
||||
angular.element(window).bind('resize', function(){
|
||||
render_panel(scope,elem,attrs);
|
||||
});
|
||||
|
||||
// Function for getting data
|
||||
function get_data(scope,elem,attrs) {
|
||||
var params = scope.params;
|
||||
var ejs = scope.ejs;
|
||||
var request = ejs.Request().indices(scope.index);
|
||||
|
||||
// Build the question part of the query
|
||||
var queries = [];
|
||||
_.each(params.queries, function(v) {
|
||||
queries.push(ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery(v || '*'),
|
||||
ejs.RangeFilter(config.timefield)
|
||||
.from(scope.from)
|
||||
.to(scope.to)
|
||||
.cache(false))
|
||||
)
|
||||
});
|
||||
|
||||
// Build the facet part
|
||||
_.each(queries, function(v) {
|
||||
request = request
|
||||
.facet(ejs.DateHistogramFacet(_.indexOf(queries,v))
|
||||
.field(config.timefield)
|
||||
.interval(params.interval)
|
||||
.facetFilter(ejs.QueryFilter(v))
|
||||
)
|
||||
})
|
||||
|
||||
// Then run it
|
||||
var results = request.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function(results) {
|
||||
scope.hits = results.hits.total;
|
||||
scope.data = results.facets;
|
||||
});
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel(scope,elem,attrs) {
|
||||
// Parse our params object
|
||||
var params = scope.params;
|
||||
|
||||
// Determine format
|
||||
var show = _.isUndefined(params.show) ? {
|
||||
bars: true, lines: false, points: false, fill: false
|
||||
} : {
|
||||
lines: _.indexOf(params.show,'lines') < 0 ? false : true,
|
||||
bars: _.indexOf(params.show,'bars') < 0 ? false : true,
|
||||
points: _.indexOf(params.show,'points') < 0 ? false : true,
|
||||
fill: _.indexOf(params.show,'fill') < 0 ? false : true
|
||||
}
|
||||
|
||||
scope.graph = [];
|
||||
// Push null values at beginning and end of timeframe
|
||||
_.each(scope.data, function(v, k) {
|
||||
var series = {};
|
||||
var data = [[scope.from.getTime(), null]];
|
||||
_.each(v.entries, function(v, k) {
|
||||
data.push([v['time'],v['count']])
|
||||
});
|
||||
data.push([scope.to.getTime(), null])
|
||||
series.data = {
|
||||
label: params.queries[k],
|
||||
data: data,
|
||||
color: params.colors[k%params.colors.length]
|
||||
};
|
||||
scope.graph.push(series.data)
|
||||
});
|
||||
|
||||
// Set barwidth based on specified interval
|
||||
var barwidth = interval_to_seconds(params.interval)*1000
|
||||
|
||||
// Populate element
|
||||
$.plot(elem, scope.graph, {
|
||||
legend: {
|
||||
position: "nw",
|
||||
labelFormatter: function(label, series) {
|
||||
return '<span class="legend">' + label + ' / ' + params.interval
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
series: {
|
||||
stack: 0,
|
||||
lines: { show: show.lines, fill: show.fill },
|
||||
bars: { show: show.bars, fill: 1, barWidth: barwidth/1.8 },
|
||||
points: { show: show.points },
|
||||
color: params.color,
|
||||
shadowSize: 1
|
||||
},
|
||||
yaxis: { min: 0, color: "#000" },
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
timeformat: "%H:%M:%S<br>%m-%d",
|
||||
label: "Datetime",
|
||||
color: "#000",
|
||||
},
|
||||
grid: {
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 0,
|
||||
borderColor: '#eee',
|
||||
color: "#eee",
|
||||
hoverable: true,
|
||||
}
|
||||
});
|
||||
//elem.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
104
scripts/date.js
Normal file
104
scripts/date.js
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
|
||||
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
|
||||
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
|
||||
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
|
||||
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
|
||||
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
|
||||
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
|
||||
if(x.month||x.months){this.addMonths(x.month||x.months);}
|
||||
if(x.year||x.years){this.addYears(x.year||x.years);}
|
||||
if(x.day||x.days){this.addDays(x.day||x.days);}
|
||||
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
|
||||
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
|
||||
if(!x.second&&x.second!==0){x.second=-1;}
|
||||
if(!x.minute&&x.minute!==0){x.minute=-1;}
|
||||
if(!x.hour&&x.hour!==0){x.hour=-1;}
|
||||
if(!x.day&&x.day!==0){x.day=-1;}
|
||||
if(!x.month&&x.month!==0){x.month=-1;}
|
||||
if(!x.year&&x.year!==0){x.year=-1;}
|
||||
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
|
||||
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
|
||||
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
|
||||
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
|
||||
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
|
||||
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
|
||||
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
|
||||
if(x.timezone){this.setTimezone(x.timezone);}
|
||||
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
|
||||
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
|
||||
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
|
||||
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
|
||||
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
|
||||
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
|
||||
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
|
||||
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
|
||||
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
|
||||
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
|
||||
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
|
||||
break;}
|
||||
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
|
||||
rx.push(r[0]);s=r[1];}
|
||||
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
|
||||
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
|
||||
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
|
||||
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
|
||||
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||
try{r=(px[i].call(this,s));}catch(e){r=null;}
|
||||
if(r){return r;}}
|
||||
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
|
||||
rx.push(r[0]);s=r[1];}
|
||||
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
|
||||
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
|
||||
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
|
||||
s=q[1];}
|
||||
if(!r){throw new $P.Exception(s);}
|
||||
if(q){throw new $P.Exception(q[1]);}
|
||||
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
|
||||
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
|
||||
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
|
||||
if(!last&&q[1].length===0){last=true;}
|
||||
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
|
||||
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
|
||||
if(rx[1].length<best[1].length){best=rx;}
|
||||
if(best[1].length===0){break;}}
|
||||
if(best[0].length===0){return best;}
|
||||
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
|
||||
best[1]=q[1];}
|
||||
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
|
||||
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
|
||||
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
|
||||
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
|
||||
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
|
||||
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
|
||||
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
|
||||
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
|
||||
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
|
||||
if(this.now){return new Date();}
|
||||
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
|
||||
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
|
||||
if(!this.unit){this.unit="day";}
|
||||
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
|
||||
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
|
||||
this[this.unit+"s"]=this.value*orient;}
|
||||
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
|
||||
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
|
||||
if(this.month&&!this.day){this.day=1;}
|
||||
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
|
||||
fn=_C[keys]=_.any.apply(null,px);}
|
||||
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
|
||||
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
|
||||
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
7
scripts/load.sh
Executable file
7
scripts/load.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
echo "Generating bulk indexable shakespeare lines with timestamp 3 hours in the past and 5 hours into the future"
|
||||
node reader.js > indexme.json
|
||||
echo "Performing bulk indexing into localhost:9200"
|
||||
curl -XPUT localhost:9200/_bulk --data-binary @indexme.json;echo
|
||||
echo
|
||||
echo "If tons of JSON just scrolled above, I've probably successfully loaded over 100,000 lines of shakespeare into localhost:9200/shakespeare"
|
2
scripts/node_modules/random-weighted-choice/.npmignore
generated
vendored
Normal file
2
scripts/node_modules/random-weighted-choice/.npmignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.sublime-*
|
||||
node_modules
|
3
scripts/node_modules/random-weighted-choice/.travis.yml
generated
vendored
Normal file
3
scripts/node_modules/random-weighted-choice/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
9
scripts/node_modules/random-weighted-choice/Makefile
generated
vendored
Normal file
9
scripts/node_modules/random-weighted-choice/Makefile
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
test:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha
|
||||
|
||||
test-w:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--growl \
|
||||
--watch
|
||||
|
||||
.PHONY: test test-w
|
75
scripts/node_modules/random-weighted-choice/README.md
generated
vendored
Normal file
75
scripts/node_modules/random-weighted-choice/README.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# Random Weighted Choice
|
||||
|
||||
[](http://travis-ci.org/parmentf/random-weighted-choice)
|
||||
|
||||
Node.js module to make a random choice among weighted elements of table.
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
$ npm install random-weighted-choice
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Although you can add several times the same id
|
||||
|
||||
var rwc = require('random-weighted-choice');
|
||||
var table = [
|
||||
{ weight: 1, id: "item1"} // Element 1
|
||||
, { weight: 1, id: "item2"} // Element 2
|
||||
, { weight: 4, id: "item3"} // Element with a 4 times likelihood
|
||||
, { weight: 2, id: "item1"} // Element 1, weight added with 2 => 3
|
||||
];
|
||||
var choosenItem = rwc(table);
|
||||
var choosenUnlikely = rwc(table, 100); // The last shall be first
|
||||
var choosenDeterministically = rwc(table, 0);
|
||||
|
||||
It is better to not use the same twice, if you want a temperature other than
|
||||
the default one (50).
|
||||
|
||||
var rwc = require('random-weighted-choice');
|
||||
var table = [
|
||||
{ weight: 1, id: "item1"} // Element 1
|
||||
, { weight: 1, id: "item2"} // Element 2
|
||||
, { weight: 4, id: "item3"} // Element with a 4 times likelihood
|
||||
, { weight: 2, id: "item4"} // Element 4
|
||||
, { weight: 2, id: "item5"}
|
||||
];
|
||||
var choosenItem = rwc(table);
|
||||
var choosenUnlikely = rwc(table, 100); // The last shall be first
|
||||
var choosenDeterministically = rwc(table, 0);
|
||||
|
||||
Without temperature (second parameter) or a 50 value, likelihoods are:
|
||||
|
||||
{ item1: 10%, item2: 10%, item3: 40%, item4: 20%, item5: 20% }
|
||||
|
||||
With a temperature value of 100:
|
||||
|
||||
{ item1: 30%, item2: 30%, item3: 0%, item4: 20%, item5: 20% }
|
||||
|
||||
With a temperature value of 0, modified weights are:
|
||||
|
||||
{ item1: 0, item2: 0, item3: 8, item4: 2, item5: 2 }
|
||||
|
||||
## Usage
|
||||
|
||||
### random-weighted-choice(Array table, Number temperature = 50)
|
||||
|
||||
Return the ``id`` of the chosen item from ``table``.
|
||||
|
||||
The ``table`` parameter should contain an Array. Each item of that Array must
|
||||
bean object, with at least ``weight`` and ``id`` property.
|
||||
|
||||
Weight values are relative to each other. They are integers.
|
||||
|
||||
When the sum of the weight values is ``null``, ``null`` is returned (can't choose).
|
||||
|
||||
When the Array is empty, ``null`` is returned.
|
||||
|
||||
More explanations on how it works on [Everything2](http://everything2.com/title/Blackboard+temperature).
|
||||
|
||||
## Also
|
||||
|
||||
* https://github.com/Schoonology/weighted
|
65
scripts/node_modules/random-weighted-choice/lib/random-weighted-choice.js
generated
vendored
Normal file
65
scripts/node_modules/random-weighted-choice/lib/random-weighted-choice.js
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*jshint node:true, laxcomma:true */
|
||||
"use strict";
|
||||
|
||||
var debug = require('debug')('rwc');
|
||||
|
||||
var RandomWeightedChoice = function (table, temperature, randomFunction, influence) {
|
||||
influence = influence || 2; // Seems fine, difficult to tune
|
||||
if (typeof(temperature)=="undefined") temperature = 50; // in [0,100], 50 is neutral
|
||||
temperature = temperature | 50;
|
||||
debug('temperature', temperature);
|
||||
var T = (temperature - 50) / 50;
|
||||
if (typeof(randomFunction)=="undefined") randomFunction = Math.random;
|
||||
|
||||
var nb = table.length;
|
||||
if(!nb) return null; // No item given.
|
||||
|
||||
var total = 0;
|
||||
table.forEach(function(element, index) {
|
||||
total += element.weight;
|
||||
});
|
||||
|
||||
var avg = total / nb;
|
||||
debug('total', total);
|
||||
debug('nb', nb);
|
||||
debug('avg', avg);
|
||||
|
||||
// Compute amplified urgencies (depending on temperature)
|
||||
var ur = {};
|
||||
var urgencySum = 0;
|
||||
table.forEach(function(element, index) {
|
||||
var urgency = element.weight + T * influence * (avg - element.weight);
|
||||
if (urgency < 0) urgency = 0;
|
||||
urgencySum += urgency;
|
||||
ur[element.id] = (ur[element.id] || 0 ) + urgency;
|
||||
});
|
||||
|
||||
var cumulatedUrgencies = {};
|
||||
var currentUrgency = 0;
|
||||
Object.keys(ur).forEach(function(id, index) {
|
||||
currentUrgency += ur[id];
|
||||
cumulatedUrgencies[id] = currentUrgency;
|
||||
});
|
||||
|
||||
if(urgencySum < 1) return null; // No weight given
|
||||
|
||||
// Choose
|
||||
var choice = randomFunction() * urgencySum;
|
||||
|
||||
debug('ur', ur);
|
||||
debug('cumulatedUrgencies', cumulatedUrgencies);
|
||||
debug('urgencySum', urgencySum);
|
||||
debug('choice', choice);
|
||||
|
||||
var ids = Object.keys(cumulatedUrgencies);
|
||||
for(var i=0; i<ids.length; i++) {
|
||||
var id = ids[i];
|
||||
var urgency = cumulatedUrgencies[id];
|
||||
if(choice <= urgency) {
|
||||
debug('return', id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = RandomWeightedChoice;
|
4
scripts/node_modules/random-weighted-choice/node_modules/debug/.npmignore
generated
vendored
Normal file
4
scripts/node_modules/random-weighted-choice/node_modules/debug/.npmignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
support
|
||||
test
|
||||
examples
|
||||
*.sock
|
47
scripts/node_modules/random-weighted-choice/node_modules/debug/History.md
generated
vendored
Normal file
47
scripts/node_modules/random-weighted-choice/node_modules/debug/History.md
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
0.7.0 / 2012-05-04
|
||||
==================
|
||||
|
||||
* Added .component to package.json
|
||||
* Added debug.component.js build
|
||||
|
||||
0.6.0 / 2012-03-16
|
||||
==================
|
||||
|
||||
* Added support for "-" prefix in DEBUG [Vinay Pulim]
|
||||
* Added `.enabled` flag to the node version [TooTallNate]
|
||||
|
||||
0.5.0 / 2012-02-02
|
||||
==================
|
||||
|
||||
* Added: humanize diffs. Closes #8
|
||||
* Added `debug.disable()` to the CS variant
|
||||
* Removed padding. Closes #10
|
||||
* Fixed: persist client-side variant again. Closes #9
|
||||
|
||||
0.4.0 / 2012-02-01
|
||||
==================
|
||||
|
||||
* Added browser variant support for older browsers [TooTallNate]
|
||||
* Added `debug.enable('project:*')` to browser variant [TooTallNate]
|
||||
* Added padding to diff (moved it to the right)
|
||||
|
||||
0.3.0 / 2012-01-26
|
||||
==================
|
||||
|
||||
* Added millisecond diff when isatty, otherwise UTC string
|
||||
|
||||
0.2.0 / 2012-01-22
|
||||
==================
|
||||
|
||||
* Added wildcard support
|
||||
|
||||
0.1.0 / 2011-12-02
|
||||
==================
|
||||
|
||||
* Added: remove colors unless stderr isatty [TooTallNate]
|
||||
|
||||
0.0.1 / 2010-01-03
|
||||
==================
|
||||
|
||||
* Initial release
|
4
scripts/node_modules/random-weighted-choice/node_modules/debug/Makefile
generated
vendored
Normal file
4
scripts/node_modules/random-weighted-choice/node_modules/debug/Makefile
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
debug.component.js: head.js debug.js tail.js
|
||||
cat $^ > $@
|
||||
|
130
scripts/node_modules/random-weighted-choice/node_modules/debug/Readme.md
generated
vendored
Normal file
130
scripts/node_modules/random-weighted-choice/node_modules/debug/Readme.md
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
# debug
|
||||
|
||||
tiny node.js debugging utility.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ npm install debug
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:
|
||||
|
||||
```js
|
||||
var debug;
|
||||
if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {
|
||||
debug = function(x) {
|
||||
var prefix = process.pid + ',' +
|
||||
(process.env.NODE_WORKER_ID ? 'Worker' : 'Master');
|
||||
console.error(prefix, x);
|
||||
};
|
||||
} else {
|
||||
debug = function() { };
|
||||
}
|
||||
```
|
||||
|
||||
This concept is extremely simple but it works well. With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
|
||||
|
||||
Example _app.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %s', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
||||
```
|
||||
|
||||
Example _worker.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('worker');
|
||||
|
||||
setInterval(function(){
|
||||
debug('doing some work');
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Millisecond diff
|
||||
|
||||
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
|
||||
|
||||

|
||||
|
||||
When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
|
||||
|
||||

|
||||
|
||||
## Conventions
|
||||
|
||||
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
|
||||
|
||||
## Wildcards
|
||||
|
||||
The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
|
||||
|
||||
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:".
|
||||
|
||||
## Browser support
|
||||
|
||||
Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`.
|
||||
|
||||
```js
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1200);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
120
scripts/node_modules/random-weighted-choice/node_modules/debug/debug.component.js
generated
vendored
Normal file
120
scripts/node_modules/random-weighted-choice/node_modules/debug/debug.component.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
;(function(){
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `name`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Type}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function debug(name) {
|
||||
if (!debug.enabled(name)) return function(){};
|
||||
|
||||
return function(fmt){
|
||||
var curr = new Date;
|
||||
var ms = curr - (debug[name] || curr);
|
||||
debug[name] = curr;
|
||||
|
||||
fmt = name
|
||||
+ ' '
|
||||
+ fmt
|
||||
+ ' +' + debug.humanize(ms);
|
||||
|
||||
// This hackery is required for IE8
|
||||
// where `console.log` doesn't have 'apply'
|
||||
window.console
|
||||
&& console.log
|
||||
&& Function.prototype.apply.call(console.log, console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently active debug mode names.
|
||||
*/
|
||||
|
||||
debug.names = [];
|
||||
debug.skips = [];
|
||||
|
||||
/**
|
||||
* Enables a debug mode by name. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} name
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.enable = function(name) {
|
||||
localStorage.debug = name;
|
||||
|
||||
var split = (name || '').split(/[\s,]+/)
|
||||
, len = split.length;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
name = split[i].replace('*', '.*?');
|
||||
if (name[0] === '-') {
|
||||
debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
|
||||
}
|
||||
else {
|
||||
debug.names.push(new RegExp('^' + name + '$'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.disable = function(){
|
||||
debug.enable('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Humanize the given `ms`.
|
||||
*
|
||||
* @param {Number} m
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
debug.humanize = function(ms) {
|
||||
var sec = 1000
|
||||
, min = 60 * 1000
|
||||
, hour = 60 * min;
|
||||
|
||||
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
|
||||
if (ms >= min) return (ms / min).toFixed(1) + 'm';
|
||||
if (ms >= sec) return (ms / sec | 0) + 's';
|
||||
return ms + 'ms';
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.enabled = function(name) {
|
||||
for (var i = 0, len = debug.skips.length; i < len; i++) {
|
||||
if (debug.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (var i = 0, len = debug.names.length; i < len; i++) {
|
||||
if (debug.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// persist
|
||||
|
||||
if (window.localStorage) debug.enable(localStorage.debug);
|
||||
module.exports = debug;
|
||||
|
||||
})();
|
116
scripts/node_modules/random-weighted-choice/node_modules/debug/debug.js
generated
vendored
Normal file
116
scripts/node_modules/random-weighted-choice/node_modules/debug/debug.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `name`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Type}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function debug(name) {
|
||||
if (!debug.enabled(name)) return function(){};
|
||||
|
||||
return function(fmt){
|
||||
var curr = new Date;
|
||||
var ms = curr - (debug[name] || curr);
|
||||
debug[name] = curr;
|
||||
|
||||
fmt = name
|
||||
+ ' '
|
||||
+ fmt
|
||||
+ ' +' + debug.humanize(ms);
|
||||
|
||||
// This hackery is required for IE8
|
||||
// where `console.log` doesn't have 'apply'
|
||||
window.console
|
||||
&& console.log
|
||||
&& Function.prototype.apply.call(console.log, console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently active debug mode names.
|
||||
*/
|
||||
|
||||
debug.names = [];
|
||||
debug.skips = [];
|
||||
|
||||
/**
|
||||
* Enables a debug mode by name. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} name
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.enable = function(name) {
|
||||
localStorage.debug = name;
|
||||
|
||||
var split = (name || '').split(/[\s,]+/)
|
||||
, len = split.length;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
name = split[i].replace('*', '.*?');
|
||||
if (name[0] === '-') {
|
||||
debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
|
||||
}
|
||||
else {
|
||||
debug.names.push(new RegExp('^' + name + '$'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.disable = function(){
|
||||
debug.enable('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Humanize the given `ms`.
|
||||
*
|
||||
* @param {Number} m
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
debug.humanize = function(ms) {
|
||||
var sec = 1000
|
||||
, min = 60 * 1000
|
||||
, hour = 60 * min;
|
||||
|
||||
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
|
||||
if (ms >= min) return (ms / min).toFixed(1) + 'm';
|
||||
if (ms >= sec) return (ms / sec | 0) + 's';
|
||||
return ms + 'ms';
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
debug.enabled = function(name) {
|
||||
for (var i = 0, len = debug.skips.length; i < len; i++) {
|
||||
if (debug.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (var i = 0, len = debug.names.length; i < len; i++) {
|
||||
if (debug.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// persist
|
||||
|
||||
if (window.localStorage) debug.enable(localStorage.debug);
|
19
scripts/node_modules/random-weighted-choice/node_modules/debug/example/app.js
generated
vendored
Normal file
19
scripts/node_modules/random-weighted-choice/node_modules/debug/example/app.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
var debug = require('../')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %s', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
24
scripts/node_modules/random-weighted-choice/node_modules/debug/example/browser.html
generated
vendored
Normal file
24
scripts/node_modules/random-weighted-choice/node_modules/debug/example/browser.html
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>debug()</title>
|
||||
<script src="../debug.js"></script>
|
||||
<script>
|
||||
// type debug.enable('*') in
|
||||
// the console and refresh :)
|
||||
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1200);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
10
scripts/node_modules/random-weighted-choice/node_modules/debug/example/wildcards.js
generated
vendored
Normal file
10
scripts/node_modules/random-weighted-choice/node_modules/debug/example/wildcards.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
var debug = {
|
||||
foo: require('../')('test:foo'),
|
||||
bar: require('../')('test:bar'),
|
||||
baz: require('../')('test:baz')
|
||||
};
|
||||
|
||||
debug.foo('foo')
|
||||
debug.bar('bar')
|
||||
debug.baz('baz')
|
22
scripts/node_modules/random-weighted-choice/node_modules/debug/example/worker.js
generated
vendored
Normal file
22
scripts/node_modules/random-weighted-choice/node_modules/debug/example/worker.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
// DEBUG=* node example/worker
|
||||
// DEBUG=worker:* node example/worker
|
||||
// DEBUG=worker:a node example/worker
|
||||
// DEBUG=worker:b node example/worker
|
||||
|
||||
var a = require('../')('worker:a')
|
||||
, b = require('../')('worker:b');
|
||||
|
||||
function work() {
|
||||
a('doing lots of uninteresting work');
|
||||
setTimeout(work, Math.random() * 1000);
|
||||
}
|
||||
|
||||
work();
|
||||
|
||||
function workb() {
|
||||
b('doing some work');
|
||||
setTimeout(workb, Math.random() * 2000);
|
||||
}
|
||||
|
||||
workb();
|
1
scripts/node_modules/random-weighted-choice/node_modules/debug/head.js
generated
vendored
Normal file
1
scripts/node_modules/random-weighted-choice/node_modules/debug/head.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
;(function(){
|
2
scripts/node_modules/random-weighted-choice/node_modules/debug/index.js
generated
vendored
Normal file
2
scripts/node_modules/random-weighted-choice/node_modules/debug/index.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
module.exports = require('./lib/debug');
|
135
scripts/node_modules/random-weighted-choice/node_modules/debug/lib/debug.js
generated
vendored
Normal file
135
scripts/node_modules/random-weighted-choice/node_modules/debug/lib/debug.js
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var tty = require('tty');
|
||||
|
||||
/**
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
module.exports = debug;
|
||||
|
||||
/**
|
||||
* Enabled debuggers.
|
||||
*/
|
||||
|
||||
var names = []
|
||||
, skips = [];
|
||||
|
||||
(process.env.DEBUG || '')
|
||||
.split(/[\s,]+/)
|
||||
.forEach(function(name){
|
||||
name = name.replace('*', '.*?');
|
||||
if (name[0] === '-') {
|
||||
skips.push(new RegExp('^' + name.substr(1) + '$'));
|
||||
} else {
|
||||
names.push(new RegExp('^' + name + '$'));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
var colors = [6, 2, 3, 4, 5, 1];
|
||||
|
||||
/**
|
||||
* Previous debug() call.
|
||||
*/
|
||||
|
||||
var prev = {};
|
||||
|
||||
/**
|
||||
* Previously assigned color.
|
||||
*/
|
||||
|
||||
var prevColor = 0;
|
||||
|
||||
/**
|
||||
* Is stdout a TTY? Colored output is disabled when `true`.
|
||||
*/
|
||||
|
||||
var isatty = tty.isatty(2);
|
||||
|
||||
/**
|
||||
* Select a color.
|
||||
*
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function color() {
|
||||
return colors[prevColor++ % colors.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Humanize the given `ms`.
|
||||
*
|
||||
* @param {Number} m
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function humanize(ms) {
|
||||
var sec = 1000
|
||||
, min = 60 * 1000
|
||||
, hour = 60 * min;
|
||||
|
||||
if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
|
||||
if (ms >= min) return (ms / min).toFixed(1) + 'm';
|
||||
if (ms >= sec) return (ms / sec | 0) + 's';
|
||||
return ms + 'ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `name`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Type}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function debug(name) {
|
||||
function disabled(){}
|
||||
disabled.enabled = false;
|
||||
|
||||
var match = skips.some(function(re){
|
||||
return re.test(name);
|
||||
});
|
||||
|
||||
if (match) return disabled;
|
||||
|
||||
match = names.some(function(re){
|
||||
return re.test(name);
|
||||
});
|
||||
|
||||
if (!match) return disabled;
|
||||
var c = color();
|
||||
|
||||
function colored(fmt) {
|
||||
var curr = new Date;
|
||||
var ms = curr - (prev[name] || curr);
|
||||
prev[name] = curr;
|
||||
|
||||
fmt = ' \033[9' + c + 'm' + name + ' '
|
||||
+ '\033[3' + c + 'm\033[90m'
|
||||
+ fmt + '\033[3' + c + 'm'
|
||||
+ ' +' + humanize(ms) + '\033[0m';
|
||||
|
||||
console.error.apply(this, arguments);
|
||||
}
|
||||
|
||||
function plain(fmt) {
|
||||
fmt = new Date().toUTCString()
|
||||
+ ' ' + name + ' ' + fmt;
|
||||
console.error.apply(this, arguments);
|
||||
}
|
||||
|
||||
colored.enabled = plain.enabled = true;
|
||||
|
||||
return isatty
|
||||
? colored
|
||||
: plain;
|
||||
}
|
32
scripts/node_modules/random-weighted-choice/node_modules/debug/package.json
generated
vendored
Normal file
32
scripts/node_modules/random-weighted-choice/node_modules/debug/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
4
scripts/node_modules/random-weighted-choice/node_modules/debug/tail.js
generated
vendored
Normal file
4
scripts/node_modules/random-weighted-choice/node_modules/debug/tail.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
module.exports = debug;
|
||||
|
||||
})();
|
35
scripts/node_modules/random-weighted-choice/package.json
generated
vendored
Normal file
35
scripts/node_modules/random-weighted-choice/package.json
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "random-weighted-choice",
|
||||
"version": "0.1.1",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"author": {
|
||||
"name": "François Parmentier"
|
||||
},
|
||||
"main": "lib/random-weighted-choice.js",
|
||||
"readmeFilename": "README.md",
|
||||
"description": "Node.js module to make a random choice among weighted elements of table.",
|
||||
"dependencies": {
|
||||
"debug": "0.7.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "1.7.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"homepage": "http://github.com/parmentf/random-weighted-choice",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/parmentf/random-weighted-choice.git"
|
||||
},
|
||||
"keywords": [
|
||||
"random",
|
||||
"weighted"
|
||||
],
|
||||
"license": "BSD",
|
||||
"readme": "# Random Weighted Choice\n\n[](http://travis-ci.org/parmentf/random-weighted-choice)\n\nNode.js module to make a random choice among weighted elements of table.\n\n## Installation\n\nWith [npm](http://npmjs.org) do:\n\n $ npm install random-weighted-choice\n\n\n## Examples\n\nAlthough you can add several times the same id\n\n var rwc = require('random-weighted-choice');\n var table = [\n { weight: 1, id: \"item1\"} // Element 1\n , { weight: 1, id: \"item2\"} // Element 2\n , { weight: 4, id: \"item3\"} // Element with a 4 times likelihood\n , { weight: 2, id: \"item1\"} // Element 1, weight added with 2 => 3\n ];\n var choosenItem = rwc(table);\n var choosenUnlikely = rwc(table, 100); // The last shall be first\n var choosenDeterministically = rwc(table, 0);\n\nIt is better to not use the same twice, if you want a temperature other than\nthe default one (50).\n\n var rwc = require('random-weighted-choice');\n var table = [\n { weight: 1, id: \"item1\"} // Element 1\n , { weight: 1, id: \"item2\"} // Element 2\n , { weight: 4, id: \"item3\"} // Element with a 4 times likelihood\n , { weight: 2, id: \"item4\"} // Element 4\n , { weight: 2, id: \"item5\"}\n ];\n var choosenItem = rwc(table);\n var choosenUnlikely = rwc(table, 100); // The last shall be first\n var choosenDeterministically = rwc(table, 0);\n\nWithout temperature (second parameter) or a 50 value, likelihoods are:\n\n { item1: 10%, item2: 10%, item3: 40%, item4: 20%, item5: 20% }\n\nWith a temperature value of 100:\n\n { item1: 30%, item2: 30%, item3: 0%, item4: 20%, item5: 20% }\n\nWith a temperature value of 0, modified weights are:\n\n { item1: 0, item2: 0, item3: 8, item4: 2, item5: 2 }\n\n## Usage\n\n### random-weighted-choice(Array table, Number temperature = 50)\n\nReturn the ``id`` of the chosen item from ``table``.\n\nThe ``table`` parameter should contain an Array. Each item of that Array must\nbean object, with at least ``weight`` and ``id`` property.\n\nWeight values are relative to each other. They are integers.\n\nWhen the sum of the weight values is ``null``, ``null`` is returned (can't choose).\n\nWhen the Array is empty, ``null`` is returned.\n\nMore explanations on how it works on [Everything2](http://everything2.com/title/Blackboard+temperature).\n\n## Also\n\n* https://github.com/Schoonology/weighted",
|
||||
"_id": "random-weighted-choice@0.1.1",
|
||||
"_from": "random-weighted-choice"
|
||||
}
|
66
scripts/node_modules/random-weighted-choice/test/test.js
generated
vendored
Normal file
66
scripts/node_modules/random-weighted-choice/test/test.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*jshint node:true, laxcomma:true */
|
||||
/*global describe:true, it:true */
|
||||
"use strict";
|
||||
|
||||
var debug = require('debug')('rwc:test');
|
||||
var assert = require('assert');
|
||||
|
||||
var rwc = require('../lib/random-weighted-choice');
|
||||
|
||||
var randomCounter = 0;
|
||||
var randomValues = [0,0.19,0.5,0.7,0.9];
|
||||
var randomMock = function(values, reset) {
|
||||
if(typeof(values)=="undefined") values = randomValues;
|
||||
if (typeof(reset)=="undefined") reset = false;
|
||||
if (reset) randomCounter = 0;
|
||||
return values[randomCounter++];
|
||||
};
|
||||
|
||||
|
||||
describe('Temperature 50', function () {
|
||||
var table = [
|
||||
{ weight: 1, id: "item1"} // Element 1
|
||||
, { weight: 1, id: "item2"} // Element 2
|
||||
, { weight: 4, id: "item3"} // Element with a 4 times likelihood
|
||||
, { weight: 2, id: "item4"} // Element 4
|
||||
, { weight: 2, id: "item5"}
|
||||
];
|
||||
|
||||
it('should return "item1"', function (){
|
||||
assert.equal('item1', rwc(table,null,randomMock));
|
||||
});
|
||||
it('should return "item2"', function (){
|
||||
assert.equal('item2', rwc(table,null,randomMock));
|
||||
});
|
||||
it('should return "item3"', function (){
|
||||
assert.equal('item3', rwc(table,null,randomMock));
|
||||
});
|
||||
it('should return "item4"', function (){
|
||||
assert.equal('item4', rwc(table,null,randomMock));
|
||||
});
|
||||
it('should return "item5"', function (){
|
||||
assert.equal('item5', rwc(table,null,randomMock));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('Empty table', function () {
|
||||
it('should return null', function () {
|
||||
assert.equal(null, rwc([]));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('One element', function () {
|
||||
it('should return the element', function () {
|
||||
assert.equal('a', rwc([{weight:1, id: 'a'}]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('No weight', function () {
|
||||
it('should return null', function () {
|
||||
assert.equal(null, rwc([{weight:0, id: 'a'}]));
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.random = randomMock;
|
282
scripts/reader.js
Normal file
282
scripts/reader.js
Normal file
@ -0,0 +1,282 @@
|
||||
require("./date.js")
|
||||
var rwc = require('random-weighted-choice');
|
||||
_ = require("./underscore.min.js")
|
||||
fs = require('fs')
|
||||
|
||||
fs.readFile('shakespeare.json', 'utf8', function (err,data) {
|
||||
i = 0;
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
var obj = JSON.parse(data);
|
||||
_.each(obj, function (o) {
|
||||
setTimeout(print_obj(o), 10000) //wait ten seconds before continuing
|
||||
});
|
||||
|
||||
function getRandomInRange(from, to, fixed) {
|
||||
return (Math.random() * (to - from) + from).toFixed(fixed) * 1;
|
||||
}
|
||||
|
||||
function print_obj(o) {
|
||||
var countries = get_countries();
|
||||
var randomnumber=Math.floor(Math.random()*28800000)
|
||||
var command = {index:{_index: "shakespeare", _type: "line", _id: i}};
|
||||
o['@timestamp'] = new Date((new Date()).getTime() -9000000 + randomnumber);
|
||||
o.geo = [getRandomInRange(-90, 90, 3),getRandomInRange(-180, 180, 3)]
|
||||
o.country = rwc(countries);
|
||||
console.log(JSON.stringify(command))
|
||||
console.log(JSON.stringify(o));
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
function get_countries() {
|
||||
return [{id:"CN",weight:1330044000},
|
||||
{id:"IN",weight:1173108018},
|
||||
{id:"US",weight:610232863},
|
||||
{id:"ID",weight:242968342},
|
||||
{id:"BR",weight:201103330},
|
||||
{id:"PK",weight:184404791},
|
||||
{id:"BD",weight:156118464},
|
||||
{id:"NG",weight:154000000},
|
||||
{id:"RU",weight:140702000},
|
||||
{id:"JP",weight:127288000},
|
||||
{id:"MX",weight:112468855},
|
||||
{id:"PH",weight:99900177},
|
||||
{id:"VN",weight:89571130},
|
||||
{id:"ET",weight:88013491},
|
||||
{id:"DE",weight:81802257},
|
||||
{id:"EG",weight:80471869},
|
||||
{id:"TR",weight:77804122},
|
||||
{id:"IR",weight:76923300},
|
||||
{id:"CD",weight:70916439},
|
||||
{id:"TH",weight:67089500},
|
||||
{id:"FR",weight:64768389},
|
||||
{id:"GB",weight:62348447},
|
||||
{id:"IT",weight:60340328},
|
||||
{id:"MM",weight:53414374},
|
||||
{id:"ZA",weight:49000000},
|
||||
{id:"KR",weight:48422644},
|
||||
{id:"ES",weight:46505963},
|
||||
{id:"UA",weight:45415596},
|
||||
{id:"CO",weight:44205293},
|
||||
{id:"TZ",weight:41892895},
|
||||
{id:"AR",weight:41343201},
|
||||
{id:"KE",weight:40046566},
|
||||
{id:"PL",weight:38500000},
|
||||
{id:"SD",weight:35000000},
|
||||
{id:"DZ",weight:34586184},
|
||||
{id:"CA",weight:33679000},
|
||||
{id:"UG",weight:33398682},
|
||||
{id:"MA",weight:31627428},
|
||||
{id:"PE",weight:29907003},
|
||||
{id:"IQ",weight:29671605},
|
||||
{id:"AF",weight:29121286},
|
||||
{id:"NP",weight:28951852},
|
||||
{id:"MY",weight:28274729},
|
||||
{id:"UZ",weight:27865738},
|
||||
{id:"VE",weight:27223228},
|
||||
{id:"SA",weight:25731776},
|
||||
{id:"GH",weight:24339838},
|
||||
{id:"YE",weight:23495361},
|
||||
{id:"KP",weight:22912177},
|
||||
{id:"TW",weight:22894384},
|
||||
{id:"SY",weight:22198110},
|
||||
{id:"MZ",weight:22061451},
|
||||
{id:"RO",weight:21959278},
|
||||
{id:"AU",weight:21515754},
|
||||
{id:"LK",weight:21513990},
|
||||
{id:"MG",weight:21281844},
|
||||
{id:"CI",weight:21058798},
|
||||
{id:"CM",weight:19294149},
|
||||
{id:"CL",weight:16746491},
|
||||
{id:"NL",weight:16645000},
|
||||
{id:"BF",weight:16241811},
|
||||
{id:"NE",weight:15878271},
|
||||
{id:"MW",weight:15447500},
|
||||
{id:"KZ",weight:15340000},
|
||||
{id:"EC",weight:14790608},
|
||||
{id:"KH",weight:14453680},
|
||||
{id:"ML",weight:13796354},
|
||||
{id:"GT",weight:13550440},
|
||||
{id:"ZM",weight:13460305},
|
||||
{id:"AO",weight:13068161},
|
||||
{id:"SN",weight:12323252},
|
||||
{id:"ZW",weight:11651858},
|
||||
{id:"CU",weight:11423000},
|
||||
{id:"RW",weight:11055976},
|
||||
{id:"GR",weight:11000000},
|
||||
{id:"CS",weight:10829175},
|
||||
{id:"PT",weight:10676000},
|
||||
{id:"TN",weight:10589025},
|
||||
{id:"TD",weight:10543464},
|
||||
{id:"CZ",weight:10476000},
|
||||
{id:"BE",weight:10403000},
|
||||
{id:"GN",weight:10324025},
|
||||
{id:"SO",weight:10112453},
|
||||
{id:"BO",weight:9947418},
|
||||
{id:"HU",weight:9930000},
|
||||
{id:"BI",weight:9863117},
|
||||
{id:"DO",weight:9823821},
|
||||
{id:"BY",weight:9685000},
|
||||
{id:"HT",weight:9648924},
|
||||
{id:"BJ",weight:9056010},
|
||||
{id:"SE",weight:9045000},
|
||||
{id:"AZ",weight:8303512},
|
||||
{id:"SS",weight:8260490},
|
||||
{id:"AT",weight:8205000},
|
||||
{id:"HN",weight:7989415},
|
||||
{id:"CH",weight:7581000},
|
||||
{id:"TJ",weight:7487489},
|
||||
{id:"IL",weight:7353985},
|
||||
{id:"RS",weight:7344847},
|
||||
{id:"BG",weight:7148785},
|
||||
{id:"HK",weight:6898686},
|
||||
{id:"TG",weight:6587239},
|
||||
{id:"LY",weight:6461454},
|
||||
{id:"JO",weight:6407085},
|
||||
{id:"PY",weight:6375830},
|
||||
{id:"LA",weight:6368162},
|
||||
{id:"PG",weight:6064515},
|
||||
{id:"SV",weight:6052064},
|
||||
{id:"NI",weight:5995928},
|
||||
{id:"ER",weight:5792984},
|
||||
{id:"KG",weight:5508626},
|
||||
{id:"DK",weight:5484000},
|
||||
{id:"SK",weight:5455000},
|
||||
{id:"SL",weight:5245695},
|
||||
{id:"FI",weight:5244000},
|
||||
{id:"NO",weight:5009150},
|
||||
{id:"AE",weight:4975593},
|
||||
{id:"TM",weight:4940916},
|
||||
{id:"CF",weight:4844927},
|
||||
{id:"SG",weight:4701069},
|
||||
{id:"GE",weight:4630000},
|
||||
{id:"IE",weight:4622917},
|
||||
{id:"BA",weight:4590000},
|
||||
{id:"CR",weight:4516220},
|
||||
{id:"HR",weight:4491000},
|
||||
{id:"MD",weight:4324000},
|
||||
{id:"NZ",weight:4252277},
|
||||
{id:"LB",weight:4125247},
|
||||
{id:"PR",weight:3916632},
|
||||
{id:"PS",weight:3800000},
|
||||
{id:"LR",weight:3685076},
|
||||
{id:"LT",weight:3565000},
|
||||
{id:"UY",weight:3477000},
|
||||
{id:"PA",weight:3410676},
|
||||
{id:"MR",weight:3205060},
|
||||
{id:"MN",weight:3086918},
|
||||
{id:"CG",weight:3039126},
|
||||
{id:"AL",weight:2986952},
|
||||
{id:"AM",weight:2968000},
|
||||
{id:"OM",weight:2967717},
|
||||
{id:"JM",weight:2847232},
|
||||
{id:"KW",weight:2789132},
|
||||
{id:"LV",weight:2217969},
|
||||
{id:"NA",weight:2128471},
|
||||
{id:"MK",weight:2061000},
|
||||
{id:"BW",weight:2029307},
|
||||
{id:"SI",weight:2007000},
|
||||
{id:"LS",weight:1919552},
|
||||
{id:"XK",weight:1800000},
|
||||
{id:"GM",weight:1593256},
|
||||
{id:"GW",weight:1565126},
|
||||
{id:"GA",weight:1545255},
|
||||
{id:"SZ",weight:1354051},
|
||||
{id:"MU",weight:1294104},
|
||||
{id:"EE",weight:1291170},
|
||||
{id:"TT",weight:1228691},
|
||||
{id:"TL",weight:1154625},
|
||||
{id:"CY",weight:1102677},
|
||||
{id:"GQ",weight:1014999},
|
||||
{id:"FJ",weight:875983},
|
||||
{id:"QA",weight:840926},
|
||||
{id:"RE",weight:776948},
|
||||
{id:"KM",weight:773407},
|
||||
{id:"GY",weight:748486},
|
||||
{id:"DJ",weight:740528},
|
||||
{id:"BH",weight:738004},
|
||||
{id:"BT",weight:699847},
|
||||
{id:"ME",weight:666730},
|
||||
{id:"SB",weight:559198},
|
||||
{id:"CV",weight:508659},
|
||||
{id:"LU",weight:497538},
|
||||
{id:"SR",weight:492829},
|
||||
{id:"MO",weight:449198},
|
||||
{id:"GP",weight:443000},
|
||||
{id:"MQ",weight:432900},
|
||||
{id:"MT",weight:403000},
|
||||
{id:"MV",weight:395650},
|
||||
{id:"BN",weight:395027},
|
||||
{id:"BZ",weight:314522},
|
||||
{id:"IS",weight:308910},
|
||||
{id:"BS",weight:301790},
|
||||
{id:"BB",weight:285653},
|
||||
{id:"EH",weight:273008},
|
||||
{id:"PF",weight:270485},
|
||||
{id:"VU",weight:221552},
|
||||
{id:"NC",weight:216494},
|
||||
{id:"GF",weight:195506},
|
||||
{id:"WS",weight:192001},
|
||||
{id:"ST",weight:175808},
|
||||
{id:"LC",weight:160922},
|
||||
{id:"GU",weight:159358},
|
||||
{id:"YT",weight:159042},
|
||||
{id:"CW",weight:141766},
|
||||
{id:"AN",weight:136197},
|
||||
{id:"TO",weight:122580},
|
||||
{id:"VI",weight:108708},
|
||||
{id:"GD",weight:107818},
|
||||
{id:"FM",weight:107708},
|
||||
{id:"VC",weight:104217},
|
||||
{id:"KI",weight:92533},
|
||||
{id:"JE",weight:90812},
|
||||
{id:"SC",weight:88340},
|
||||
{id:"AG",weight:86754},
|
||||
{id:"AD",weight:84000},
|
||||
{id:"IM",weight:75049},
|
||||
{id:"DM",weight:72813},
|
||||
{id:"AW",weight:71566},
|
||||
{id:"MH",weight:65859},
|
||||
{id:"BM",weight:65365},
|
||||
{id:"GG",weight:65228},
|
||||
{id:"AS",weight:57881},
|
||||
{id:"GL",weight:56375},
|
||||
{id:"MP",weight:53883},
|
||||
{id:"KN",weight:49898},
|
||||
{id:"FO",weight:48228},
|
||||
{id:"KY",weight:44270},
|
||||
{id:"SX",weight:37429},
|
||||
{id:"MF",weight:35925},
|
||||
{id:"LI",weight:35000},
|
||||
{id:"MC",weight:32965},
|
||||
{id:"SM",weight:31477},
|
||||
{id:"GI",weight:27884},
|
||||
{id:"AX",weight:26711},
|
||||
{id:"VG",weight:21730},
|
||||
{id:"CK",weight:21388},
|
||||
{id:"TC",weight:20556},
|
||||
{id:"PW",weight:19907},
|
||||
{id:"BQ",weight:18012},
|
||||
{id:"WF",weight:16025},
|
||||
{id:"AI",weight:13254},
|
||||
{id:"TV",weight:10472},
|
||||
{id:"NR",weight:10065},
|
||||
{id:"MS",weight:9341},
|
||||
{id:"BL",weight:8450},
|
||||
{id:"SH",weight:7460},
|
||||
{id:"PM",weight:7012},
|
||||
{id:"IO",weight:4000},
|
||||
{id:"FK",weight:2638},
|
||||
{id:"SJ",weight:2550},
|
||||
{id:"NU",weight:2166},
|
||||
{id:"NF",weight:1828},
|
||||
{id:"CX",weight:1500},
|
||||
{id:"TK",weight:1466},
|
||||
{id:"VA",weight:921},
|
||||
{id:"CC",weight:628},
|
||||
{id:"TF",weight:140},
|
||||
{id:"PN",weight:46},
|
||||
{id:"GS",weight:30}];
|
||||
}
|
||||
});
|
1
scripts/shakespeare.json
Normal file
1
scripts/shakespeare.json
Normal file
File diff suppressed because one or more lines are too long
32
scripts/underscore.min.js
vendored
Normal file
32
scripts/underscore.min.js
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
// Underscore.js 1.3.3
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable under the MIT license.
|
||||
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore
|
||||
(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
|
||||
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break;
|
||||
g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,
|
||||
c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
|
||||
a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
|
||||
c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,
|
||||
a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
|
||||
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&
|
||||
(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};
|
||||
j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,
|
||||
0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,
|
||||
e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=
|
||||
i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=
|
||||
1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=
|
||||
i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=
|
||||
g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));
|
||||
return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&
|
||||
c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=
|
||||
function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"};
|
||||
b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,
|
||||
b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId=
|
||||
function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape||
|
||||
u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};
|
||||
b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d,
|
||||
this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
|
Loading…
Reference in New Issue
Block a user