Skip to content

Instantly share code, notes, and snippets.

@danharr
Last active August 29, 2015 14:06
Show Gist options
  • Save danharr/e80684642c7aadb188ba to your computer and use it in GitHub Desktop.
Save danharr/e80684642c7aadb188ba to your computer and use it in GitHub Desktop.
Radian | Angular | d3
'use strict';
function EgCtrl(plotLib, $http, $scope, $location) {
plotLib.midMonths = function(ms, y) {
return ms.map(function(m) { return new Date(y, m, 15); });
};
// Turn a vector of [[x1,y1], [x2,y2], ..., [xn,yn]] into a vector
// of y-values interpolated to [f, ..., t].
plotLib.fillIn = function(d, f, t) {
var ft = t - f + 1;
var ys = new Array(ft);
var x1 = d[0][0], xn = d[d.length-1][0];
var y1 = d[0][1], yn = d[d.length-1][1];
if (d.length == 1)
for (var i = 0; i < ft; ++i) ys[i] = y1;
else {
var i = 0;
if (f < x1) {
var delta = (d[1][1] - y1) / (d[1][0] - x1);
var yf = y1 - delta * (x1 - f);
for (; i < x1-f; ++i) ys[i] = yf + delta * i;
}
ys[i] = y1;
var j = 1;
while (j < d.length) {
var ym = d[j-1][1], yp = d[j][1], xm = d[j-1][0], xp = d[j][0];
var delta = (yp - ym) / (xp - xm);
for (; x1+i < d[j][0]; ++i) ys[i] = ym + delta * (x1+i - xm);
if (i < ft) ys[i++] = d[j++][1];
}
if (i < ft) {
var delta = (yn - d[d.length-2][1]) / (xn - d[d.length-2][0]);
for (var i0 = i; i < ft; ++i) ys[i] = yn + delta * (i-i0+1);
}
}
return ys;
};
$scope.loadStockData = function() {
$http.get('/data/stocks/' + $scope.dset + '.csv').
success(function(data) {
$scope.datavalues = data;
});
};
$scope.stockInit = function() {
$scope.dset = 'CSCO';
$scope.loadStockData($scope.dset);
};
$scope.$watch('$location.hash', function() {
var url = "http://" + location.host + "/eg/" +
location.hash.slice(2) + ".html";
$http.get(url).success(function(res) {
res = res.replace(/<h3>(.|\n)*<\/h3>\n\n/m, "");
$('div.container pre.include-source').remove();
var ctr = $('div.container');
ctr.append('<pre class="include-source">' +
'<code class="html"></code></pre>');
var code = $($(ctr.children()[ctr.children().length-1]).children()[0]);
code.text(res);
code.highlight();
});
});
}
EgCtrl.$inject = ['plotLib', '$http', '$scope', '$location'];
var negs = 85;
var eggrps = [ { title: "Plot types",
items: [["Basic plot; CSV data", 1],
["Basic plot; JSON data", 2],
["Bar charts", 11],
["Func. plots", 12],
["Func. plots", 13],
["Basic points plot", 17],
["Textual points plot", 81],
["Range attributes", 18],
["Log axes", 19],
["Second axes", 20],
["Bar chart", 21],
["Bar chart (px width)", 51],
["Test", 22],
["Histogram #1", 32],
["Histogram #2", 53],
["Histogram #3", 54],
["Histogram #4", 74],
["Simple area plot", 35],
["Rug plots", 73],
["Simple heatmap", 52]] },
{ title: "UI examples",
items: [["Int. legend; fading", 3],
["X-axis zoom", 4],
["Stroke fade UI", 5],
["Stroke colour UI", 6],
["X/Y variable UI", 7],
["UI in layout #1", 69],
["UI in layout #2", 70],
["UI in layout #3", 71],
["Axis transformations", 76]] },
{ title: "Data access",
items: [["Date handling", 9],
["JSON date handling", 65],
["Hierarchical JSON data", 66],
["Data aggr. funcs.", 10],
["Vectorisation", 14],
["Data binding", 15],
["Integer pluck", 23],
["Pluck expr. test", 40],
["Data via URL", 34],
["Data via URL (binding)", 67],
["Data via URL (ng-model)", 68],
["Missing data", 79]] },
{ title: "Layout",
items: [["Layout #1", 42],
["Layout #2", 43],
["Layout #3", 44],
["Layout #4", 45],
["Layout #5", 46],
["Layout #6", 47],
["Simple plot stack", 8],
["Complex plot stack", 63],
["Nested plot stacks", 64]] },
{ title: "Palettes",
items: [["Norm. palette", 25],
["Disc. palette", 26],
["Disc. pal. (mark)", 27],
["Func. + pal.", 28],
["Func. + abs. pal.", 29],
["Abs. pal. terrain", 30],
["Banded pal.", 33],
["Comp. pal. #1", 36],
["Comp. pal. #2", 37],
["Gradient pal.", 38],
["Categorical palettes", 50]] },
{ title: "Discrete data",
items: [["Categorical points", 59],
["Categorical bars #1", 60],
["Categorical bars #2", 61],
["Categorical bars #3", 62],
["Categorical lines", 82]] },
{ title: "Formatting",
items: [["<plot-options>", 16],
["Plot titles #1", 41],
["Font selection #1", 49],
["Font selection #2", 72],
["Scientific notation", 55],
["Date axis formatting", 56],
["Explicit ticks", 57],
["Tick sizes/padding", 58],
["Legends", 77],
["Legends #2", 78],
["Legends #3 (metadata)", 83]] },
{ title: "Bigger examples",
items: [["Health & wealth", 39]] },
{ title: "Bugs",
items: [["Tom's data example", 24],
["Test", 22],
["plot-options bug", 31],
["Palettes & ng-repeat", 48],
["Histogram nonsense", 75],
["Tom's area plots", 80],
["JSON dates & metadata", 84],
["Beat's date problem", 85]] } ];
angular.module('myApp', ['radian']).
config(['$routeProvider', function($routeProvider) {
for (var eg = 1; eg <= negs; ++eg) {
var n = (eg < 10 ? '0' : '') + eg;
$routeProvider.when('/' + n, { templateUrl: 'eg/' + n + '.html',
controller: EgCtrl });
}
$routeProvider.otherwise({ redirectTo: '/01' });
}]).
controller('BaseController',
['$rootScope', function($rootScope) {
$rootScope.egs = [];
for (var grp = 0; grp < eggrps.length; ++grp) {
var grpitems = [];
for (var i = 0; i < eggrps[grp].items.length; ++i) {
var egtitle = eggrps[grp].items[i][0];
var eg = eggrps[grp].items[i][1];
var n = (eg < 10 ? '0' : '') + eg;
grpitems.push({ title: egtitle, link: "#/" + n });
}
$rootScope.egs.push({ title: eggrps[grp].title, items: grpitems,
id: "grp" + grp, idhash: "#grp" + grp });
}
$rootScope.pals = { bgr: '0 blue; 0.5 grey; 1 red',
gyo: '0 green; 0.5 yellow; 1 orange' };
}]);
// Generated by browserify
(function(){var require = function (file, cwd) {
var resolved = require.resolve(file, cwd || '/');
var mod = require.modules[resolved];
if (!mod) throw new Error(
'Failed to resolve module ' + file + ', tried ' + resolved
);
var cached = require.cache[resolved];
var res = cached? cached.exports : mod();
return res;
};
require.paths = [];
require.modules = {};
require.cache = {};
require.extensions = [".js",".coffee",".json"];
require._core = {
'assert': true,
'events': true,
'fs': true,
'path': true,
'vm': true
};
require.resolve = (function () {
return function (x, cwd) {
if (!cwd) cwd = '/';
if (require._core[x]) return x;
var path = require.modules.path();
cwd = path.resolve('/', cwd);
var y = cwd || '/';
if (x.match(/^(?:\.\.?\/|\/)/)) {
var m = loadAsFileSync(path.resolve(y, x))
|| loadAsDirectorySync(path.resolve(y, x));
if (m) return m;
}
var n = loadNodeModulesSync(x, y);
if (n) return n;
throw new Error("Cannot find module '" + x + "'");
function loadAsFileSync (x) {
x = path.normalize(x);
if (require.modules[x]) {
return x;
}
for (var i = 0; i < require.extensions.length; i++) {
var ext = require.extensions[i];
if (require.modules[x + ext]) return x + ext;
}
}
function loadAsDirectorySync (x) {
x = x.replace(/\/+$/, '');
var pkgfile = path.normalize(x + '/package.json');
if (require.modules[pkgfile]) {
var pkg = require.modules[pkgfile]();
var b = pkg.browserify;
if (typeof b === 'object' && b.main) {
var m = loadAsFileSync(path.resolve(x, b.main));
if (m) return m;
}
else if (typeof b === 'string') {
var m = loadAsFileSync(path.resolve(x, b));
if (m) return m;
}
else if (pkg.main) {
var m = loadAsFileSync(path.resolve(x, pkg.main));
if (m) return m;
}
}
return loadAsFileSync(x + '/index');
}
function loadNodeModulesSync (x, start) {
var dirs = nodeModulesPathsSync(start);
for (var i = 0; i < dirs.length; i++) {
var dir = dirs[i];
var m = loadAsFileSync(dir + '/' + x);
if (m) return m;
var n = loadAsDirectorySync(dir + '/' + x);
if (n) return n;
}
var m = loadAsFileSync(x);
if (m) return m;
}
function nodeModulesPathsSync (start) {
var parts;
if (start === '/') parts = [ '' ];
else parts = path.normalize(start).split('/');
var dirs = [];
for (var i = parts.length - 1; i >= 0; i--) {
if (parts[i] === 'node_modules') continue;
var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
dirs.push(dir);
}
return dirs;
}
};
})();
require.alias = function (from, to) {
var path = require.modules.path();
var res = null;
try {
res = require.resolve(from + '/package.json', '/');
}
catch (err) {
res = require.resolve(from, '/');
}
var basedir = path.dirname(res);
var keys = (Object.keys || function (obj) {
var res = [];
for (var key in obj) res.push(key);
return res;
})(require.modules);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (key.slice(0, basedir.length + 1) === basedir + '/') {
var f = key.slice(basedir.length);
require.modules[to + f] = require.modules[basedir + f];
}
else if (key === basedir) {
require.modules[to] = require.modules[basedir];
}
}
};
(function () {
var process = {};
var global = typeof window !== 'undefined' ? window : {};
var definedProcess = false;
require.define = function (filename, fn) {
if (!definedProcess && require.modules.__browserify_process) {
process = require.modules.__browserify_process();
definedProcess = true;
}
var dirname = require._core[filename]
? ''
: require.modules.path().dirname(filename)
;
var require_ = function (file) {
var requiredModule = require(file, dirname);
var cached = require.cache[require.resolve(file, dirname)];
if (cached && cached.parent === null) {
cached.parent = module_;
}
return requiredModule;
};
require_.resolve = function (name) {
return require.resolve(name, dirname);
};
require_.modules = require.modules;
require_.define = require.define;
require_.cache = require.cache;
var module_ = {
id : filename,
filename: filename,
exports : {},
loaded : false,
parent: null
};
require.modules[filename] = function () {
require.cache[filename] = module_;
fn.call(
module_.exports,
require_,
module_,
module_.exports,
dirname,
filename,
process,
global
);
module_.loaded = true;
return module_.exports;
};
};
})();
require.define("path",function(require,module,exports,__dirname,__filename,process,global){function filter (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
if (fn(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length; i >= 0; i--) {
var last = parts[i];
if (last == '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Regex to split a filename into [*, dir, basename, ext]
// posix version
var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0)
? arguments[i]
: process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string' || !path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = path.charAt(0) === '/',
trailingSlash = path.slice(-1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function(p, index) {
return p && typeof p === 'string';
}).join('/'));
};
exports.dirname = function(path) {
var dir = splitPathRe.exec(path)[1] || '';
var isWindows = false;
if (!dir) {
// No dirname
return '.';
} else if (dir.length === 1 ||
(isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
// It is just a slash or a drive letter with a slash
return dir;
} else {
// It is a full dirname, strip trailing slash
return dir.substring(0, dir.length - 1);
}
};
exports.basename = function(path, ext) {
var f = splitPathRe.exec(path)[2] || '';
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function(path) {
return splitPathRe.exec(path)[3] || '';
};
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
});
require.define("__browserify_process",function(require,module,exports,__dirname,__filename,process,global){var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'browserify-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('browserify-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
if (name === 'evals') return (require)('vm')
else throw new Error('No such module. (Possibly not yet loaded)')
};
(function () {
var cwd = '/';
var path;
process.cwd = function () { return cwd };
process.chdir = function (dir) {
if (!path) path = require('path');
cwd = path.resolve(dir, cwd);
};
})();
});
require.define("/package.json",function(require,module,exports,__dirname,__filename,process,global){module.exports = {"main":"escodegen.js"}
});
require.define("/escodegen.js",function(require,module,exports,__dirname,__filename,process,global){/*
Copyright (C) 2012 Michael Ficarra <escodegen.copyright@michael.ficarra.me>
Copyright (C) 2012 Robert Gust-Bardon <donate@robert.gust-bardon.org>
Copyright (C) 2012 John Freeman <jfreeman08@gmail.com>
Copyright (C) 2011-2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*jslint bitwise:true */
/*global escodegen:true, exports:true, generateStatement:true, generateExpression:true, generateFunctionBody:true, process:true, require:true, define:true*/
(function () {
'use strict';
var Syntax,
Precedence,
BinaryPrecedence,
Regex,
VisitorKeys,
VisitorOption,
SourceNode,
isArray,
base,
indent,
json,
renumber,
hexadecimal,
quotes,
escapeless,
newline,
space,
parentheses,
semicolons,
safeConcatenation,
directive,
extra,
parse,
sourceMap,
traverse;
traverse = require('estraverse').traverse;
Syntax = {
AssignmentExpression: 'AssignmentExpression',
ArrayExpression: 'ArrayExpression',
ArrayPattern: 'ArrayPattern',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ComprehensionBlock: 'ComprehensionBlock',
ComprehensionExpression: 'ComprehensionExpression',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
DebuggerStatement: 'DebuggerStatement',
EmptyStatement: 'EmptyStatement',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
Identifier: 'Identifier',
IfStatement: 'IfStatement',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
PluckExpression: 'PluckExpression',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
ObjectPattern: 'ObjectPattern',
Program: 'Program',
Property: 'Property',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement',
YieldExpression: 'YieldExpression',
};
Precedence = {
Sequence: 0,
Assignment: 1,
Conditional: 2,
LogicalOR: 3,
LogicalAND: 4,
BitwiseOR: 5,
BitwiseXOR: 6,
BitwiseAND: 7,
Equality: 8,
Relational: 9,
BitwiseSHIFT: 10,
Additive: 11,
Multiplicative: 12,
Unary: 13,
Postfix: 14,
Call: 15,
New: 16,
Member: 17,
Primary: 18
};
BinaryPrecedence = {
'||': Precedence.LogicalOR,
'&&': Precedence.LogicalAND,
'|': Precedence.BitwiseOR,
'^': Precedence.BitwiseXOR,
'&': Precedence.BitwiseAND,
'==': Precedence.Equality,
'!=': Precedence.Equality,
'===': Precedence.Equality,
'!==': Precedence.Equality,
'is': Precedence.Equality,
'isnt': Precedence.Equality,
'<': Precedence.Relational,
'>': Precedence.Relational,
'<=': Precedence.Relational,
'>=': Precedence.Relational,
'in': Precedence.Relational,
'instanceof': Precedence.Relational,
'<<': Precedence.BitwiseSHIFT,
'>>': Precedence.BitwiseSHIFT,
'>>>': Precedence.BitwiseSHIFT,
'+': Precedence.Additive,
'-': Precedence.Additive,
'*': Precedence.Multiplicative,
'%': Precedence.Multiplicative,
'/': Precedence.Multiplicative
};
Regex = {
NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
};
function getDefaultOptions() {
// default options
return {
indent: null,
base: null,
parse: null,
comment: false,
format: {
indent: {
style: ' ',
base: 0,
adjustMultilineComment: false
},
json: false,
renumber: false,
hexadecimal: false,
quotes: 'single',
escapeless: false,
compact: false,
parentheses: true,
semicolons: true,
safeConcatenation: false
},
moz: {
starlessGenerator: false,
parenthesizedComprehensionBlock: false
},
sourceMap: null,
sourceMapRoot: null,
sourceMapWithCode: false,
directive: false,
verbatim: null
};
}
function stringToArray(str) {
var length = str.length,
result = [],
i;
for (i = 0; i < length; i += 1) {
result[i] = str.charAt(i);
}
return result;
}
function stringRepeat(str, num) {
var result = '';
for (num |= 0; num > 0; num >>>= 1, str += str) {
if (num & 1) {
result += str;
}
}
return result;
}
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray(array) {
return Object.prototype.toString.call(array) === '[object Array]';
};
}
// Fallback for the non SourceMap environment
function SourceNodeMock(line, column, filename, chunk) {
var result = [];
function flatten(input) {
var i, iz;
if (isArray(input)) {
for (i = 0, iz = input.length; i < iz; ++i) {
flatten(input[i]);
}
} else if (input instanceof SourceNodeMock) {
result.push(input);
} else if (typeof input === 'string' && input) {
result.push(input);
}
}
flatten(chunk);
this.children = result;
}
SourceNodeMock.prototype.toString = function toString() {
var res = '', i, iz, node;
for (i = 0, iz = this.children.length; i < iz; ++i) {
node = this.children[i];
if (node instanceof SourceNodeMock) {
res += node.toString();
} else {
res += node;
}
}
return res;
};
SourceNodeMock.prototype.replaceRight = function replaceRight(pattern, replacement) {
var last = this.children[this.children.length - 1];
if (last instanceof SourceNodeMock) {
last.replaceRight(pattern, replacement);
} else if (typeof last === 'string') {
this.children[this.children.length - 1] = last.replace(pattern, replacement);
} else {
this.children.push(''.replace(pattern, replacement));
}
return this;
};
SourceNodeMock.prototype.join = function join(sep) {
var i, iz, result;
result = [];
iz = this.children.length;
if (iz > 0) {
for (i = 0, iz -= 1; i < iz; ++i) {
result.push(this.children[i], sep);
}
result.push(this.children[iz]);
this.children = result;
}
return this;
};
function hasLineTerminator(str) {
return /[\r\n]/g.test(str);
}
function endsWithLineTerminator(str) {
var ch = str.charAt(str.length - 1);
return ch === '\r' || ch === '\n';
}
function shallowCopy(obj) {
var ret = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = obj[key];
}
}
return ret;
}
function deepCopy(obj) {
var ret = {}, key, val;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
val = obj[key];
if (typeof val === 'object' && val !== null) {
ret[key] = deepCopy(val);
} else {
ret[key] = val;
}
}
}
return ret;
}
function updateDeeply(target, override) {
var key, val;
function isHashObject(target) {
return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
}
for (key in override) {
if (override.hasOwnProperty(key)) {
val = override[key];
if (isHashObject(val)) {
if (isHashObject(target[key])) {
updateDeeply(target[key], val);
} else {
target[key] = updateDeeply({}, val);
}
} else {
target[key] = val;
}
}
}
return target;
}
function generateNumber(value) {
var result, point, temp, exponent, pos;
if (value !== value) {
throw new Error('Numeric literal whose value is NaN');
}
if (value < 0 || (value === 0 && 1 / value < 0)) {
throw new Error('Numeric literal whose value is negative');
}
if (value === 1 / 0) {
return json ? 'null' : renumber ? '1e400' : '1e+400';
}
result = '' + value;
if (!renumber || result.length < 3) {
return result;
}
point = result.indexOf('.');
if (!json && result.charAt(0) === '0' && point === 1) {
point = 0;
result = result.slice(1);
}
temp = result;
result = result.replace('e+', 'e');
exponent = 0;
if ((pos = temp.indexOf('e')) > 0) {
exponent = +temp.slice(pos + 1);
temp = temp.slice(0, pos);
}
if (point >= 0) {
exponent -= temp.length - point - 1;
temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
}
pos = 0;
while (temp.charAt(temp.length + pos - 1) === '0') {
pos -= 1;
}
if (pos !== 0) {
exponent -= pos;
temp = temp.slice(0, pos);
}
if (exponent !== 0) {
temp += 'e' + exponent;
}
if ((temp.length < result.length ||
(hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&
+temp === value) {
result = temp;
}
return result;
}
function escapeAllowedCharacter(ch, next) {
var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
switch (ch) {
case '\b':
result += 'b';
break;
case '\f':
result += 'f';
break;
case '\t':
result += 't';
break;
default:
if (json || code > 0xff) {
result += 'u' + '0000'.slice(hex.length) + hex;
} else if (ch === '\u0000' && '0123456789'.indexOf(next) < 0) {
result += '0';
} else if (ch === '\v') {
result += 'v';
} else {
result += 'x' + '00'.slice(hex.length) + hex;
}
break;
}
return result;
}
function escapeDisallowedCharacter(ch) {
var result = '\\';
switch (ch) {
case '\\':
result += '\\';
break;
case '\n':
result += 'n';
break;
case '\r':
result += 'r';
break;
case '\u2028':
result += 'u2028';
break;
case '\u2029':
result += 'u2029';
break;
default:
throw new Error('Incorrectly classified character');
}
return result;
}
function escapeDirective(str) {
var i, iz, ch, single, buf, quote;
buf = str;
if (typeof buf[0] === 'undefined') {
buf = stringToArray(buf);
}
quote = quotes === 'double' ? '"' : '\'';
for (i = 0, iz = buf.length; i < iz; i += 1) {
ch = buf[i];
if (ch === '\'') {
quote = '"';
break;
} else if (ch === '"') {
quote = '\'';
break;
} else if (ch === '\\') {
i += 1;
}
}
return quote + str + quote;
}
function escapeString(str) {
var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
if (typeof str[0] === 'undefined') {
str = stringToArray(str);
}
for (i = 0, len = str.length; i < len; i += 1) {
ch = str[i];
if (ch === '\'') {
singleQuotes += 1;
} else if (ch === '"') {
doubleQuotes += 1;
} else if (ch === '/' && json) {
result += '\\';
} else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
result += escapeDisallowedCharacter(ch);
continue;
} else if ((json && ch < ' ') || !(json || escapeless || (ch >= ' ' && ch <= '~'))) {
result += escapeAllowedCharacter(ch, str[i + 1]);
continue;
}
result += ch;
}
single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
str = result;
result = single ? '\'' : '"';
if (typeof str[0] === 'undefined') {
str = stringToArray(str);
}
for (i = 0, len = str.length; i < len; i += 1) {
ch = str[i];
if ((ch === '\'' && single) || (ch === '"' && !single)) {
result += '\\';
}
result += ch;
}
return result + (single ? '\'' : '"');
}
function isWhiteSpace(ch) {
return '\t\v\f \xa0'.indexOf(ch) >= 0 || (ch.charCodeAt(0) >= 0x1680 && '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff'.indexOf(ch) >= 0);
}
function isLineTerminator(ch) {
return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
}
function isIdentifierPart(ch) {
return (ch === '$') || (ch === '_') || (ch === '\\') ||
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
((ch >= '0') && (ch <= '9')) ||
((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
}
function toSourceNode(generated, node) {
if (node == null) {
if (generated instanceof SourceNode) {
return generated;
} else {
node = {};
}
}
if (node.loc == null) {
return new SourceNode(null, null, sourceMap, generated);
}
return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated);
}
function join(left, right) {
var leftSource = toSourceNode(left).toString(),
rightSource = toSourceNode(right).toString(),
leftChar = leftSource.charAt(leftSource.length - 1),
rightChar = rightSource.charAt(0);
if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
return [left, ' ', right];
} else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
return [left, right];
}
return [left, space, right];
}
function addIndent(stmt) {
return [base, stmt];
}
function withIndent(fn) {
var previousBase, result;
previousBase = base;
base += indent;
result = fn.call(this, base);
base = previousBase;
return result;
}
function calculateSpaces(str) {
var i;
for (i = str.length - 1; i >= 0; i -= 1) {
if (isLineTerminator(str.charAt(i))) {
break;
}
}
return (str.length - 1) - i;
}
function adjustMultilineComment(value, specialBase) {
var array, i, len, line, j, ch, spaces, previousBase;
array = value.split(/\r\n|[\r\n]/);
spaces = Number.MAX_VALUE;
// first line doesn't have indentation
for (i = 1, len = array.length; i < len; i += 1) {
line = array[i];
j = 0;
while (j < line.length && isWhiteSpace(line[j])) {
j += 1;
}
if (spaces > j) {
spaces = j;
}
}
if (typeof specialBase !== 'undefined') {
// pattern like
// {
// var t = 20; /*
// * this is comment
// */
// }
previousBase = base;
if (array[1][spaces] === '*') {
specialBase += ' ';
}
base = specialBase;
} else {
if (spaces & 1) {
// /*
// *
// */
// If spaces are odd number, above pattern is considered.
// We waste 1 space.
spaces -= 1;
}
previousBase = base;
}
for (i = 1, len = array.length; i < len; i += 1) {
array[i] = toSourceNode(addIndent(array[i].slice(spaces))).join('');
}
base = previousBase;
return array.join('\n');
}
function generateComment(comment, specialBase) {
if (comment.type === 'Line') {
if (endsWithLineTerminator(comment.value)) {
return '//' + comment.value;
} else {
// Always use LineTerminator
return '//' + comment.value + '\n';
}
}
if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
}
return '/*' + comment.value + '*/';
}
function addCommentsToStatement(stmt, result) {
var i, len, comment, save, node, tailingToStatement, specialBase, fragment;
if (stmt.leadingComments && stmt.leadingComments.length > 0) {
save = result;
comment = stmt.leadingComments[0];
result = [];
if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
result.push('\n');
}
result.push(generateComment(comment));
if (!endsWithLineTerminator(toSourceNode(result).toString())) {
result.push('\n');
}
for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
comment = stmt.leadingComments[i];
fragment = [generateComment(comment)];
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
fragment.push('\n');
}
result.push(addIndent(fragment));
}
result.push(addIndent(save));
}
if (stmt.trailingComments) {
tailingToStatement = !endsWithLineTerminator(toSourceNode(result).toString());
specialBase = stringRepeat(' ', calculateSpaces(toSourceNode([base, result, indent]).toString()));
for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
comment = stmt.trailingComments[i];
if (tailingToStatement) {
// We assume target like following script
//
// var t = 20; /**
// * This is comment of t
// */
if (i === 0) {
// first case
result = [result, indent];
} else {
result = [result, specialBase];
}
result.push(generateComment(comment, specialBase));
} else {
result = [result, addIndent(generateComment(comment))];
}
if (i !== len - 1 && !endsWithLineTerminator(toSourceNode(result).toString())) {
result = [result, '\n'];
}
}
}
return result;
}
function parenthesize(text, current, should) {
if (current < should) {
return ['(', text, ')'];
}
return text;
}
function maybeBlock(stmt, semicolonOptional, functionBody) {
var result, noLeadingComment;
noLeadingComment = !extra.comment || !stmt.leadingComments;
if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
return [space, generateStatement(stmt, { functionBody: functionBody })];
}
if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
return ';';
}
withIndent(function () {
result = [newline, addIndent(generateStatement(stmt, { semicolonOptional: semicolonOptional, functionBody: functionBody }))];
});
return result;
}
function maybeBlockSuffix(stmt, result) {
var ends = endsWithLineTerminator(toSourceNode(result).toString());
if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {
return [result, space];
}
if (ends) {
return [result, base];
}
return [result, newline, base];
}
function generateVerbatim(expr, option) {
var i, result;
result = expr[extra.verbatim].split(/\r\n|\n/);
for (i = 1; i < result.length; i++) {
result[i] = newline + base + result[i];
}
result = parenthesize(result, Precedence.Sequence, option.precedence);
return toSourceNode(result, expr);
}
function generateFunctionBody(node) {
var result, i, len, expr;
result = ['('];
for (i = 0, len = node.params.length; i < len; i += 1) {
result.push(node.params[i].name);
if (i + 1 < len) {
result.push(',' + space);
}
}
result.push(')');
if (node.expression) {
result.push(space);
expr = generateExpression(node.body, {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
});
if (expr.toString().charAt(0) === '{') {
expr = ['(', expr, ')'];
}
result.push(expr);
} else {
result.push(maybeBlock(node.body, false, true));
}
return result;
}
function generateExpression(expr, option) {
var result, precedence, type, currentPrecedence, i, len, raw, fragment, multiline, leftChar, leftSource, rightChar, rightSource, allowIn, allowCall, allowUnparenthesizedNew, property, key, value;
precedence = option.precedence;
allowIn = option.allowIn;
allowCall = option.allowCall;
type = expr.type || option.type;
if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {
return generateVerbatim(expr, option);
}
switch (type) {
case Syntax.SequenceExpression:
result = [];
allowIn |= (Precedence.Sequence < precedence);
for (i = 0, len = expr.expressions.length; i < len; i += 1) {
result.push(generateExpression(expr.expressions[i], {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
}));
if (i + 1 < len) {
result.push(',' + space);
}
}
result = parenthesize(result, Precedence.Sequence, precedence);
break;
case Syntax.AssignmentExpression:
allowIn |= (Precedence.Assignment < precedence);
result = parenthesize(
[
generateExpression(expr.left, {
precedence: Precedence.Call,
allowIn: allowIn,
allowCall: true
}),
space + expr.operator + space,
generateExpression(expr.right, {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
})
],
Precedence.Assignment,
precedence
);
break;
case Syntax.ConditionalExpression:
allowIn |= (Precedence.Conditional < precedence);
result = parenthesize(
[
generateExpression(expr.test, {
precedence: Precedence.LogicalOR,
allowIn: allowIn,
allowCall: true
}),
space + '?' + space,
generateExpression(expr.consequent, {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
}),
space + ':' + space,
generateExpression(expr.alternate, {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
})
],
Precedence.Conditional,
precedence
);
break;
case Syntax.LogicalExpression:
case Syntax.BinaryExpression:
currentPrecedence = BinaryPrecedence[expr.operator];
allowIn |= (currentPrecedence < precedence);
result = join(
generateExpression(expr.left, {
precedence: currentPrecedence,
allowIn: allowIn,
allowCall: true
}),
expr.operator
);
fragment = generateExpression(expr.right, {
precedence: currentPrecedence + 1,
allowIn: allowIn,
allowCall: true
});
if (expr.operator === '/' && fragment.toString().charAt(0) === '/') {
// If '/' concats with '/', it is interpreted as comment start
result.push(' ', fragment);
} else {
result = join(result, fragment);
}
if (expr.operator === 'in' && !allowIn) {
result = ['(', result, ')'];
} else {
result = parenthesize(result, currentPrecedence, precedence);
}
break;
case Syntax.CallExpression:
result = [generateExpression(expr.callee, {
precedence: Precedence.Call,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: false
})];
result.push('(');
for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
result.push(generateExpression(expr['arguments'][i], {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
}));
if (i + 1 < len) {
result.push(',' + space);
}
}
result.push(')');
if (!allowCall) {
result = ['(', result, ')'];
} else {
result = parenthesize(result, Precedence.Call, precedence);
}
break;
case Syntax.NewExpression:
len = expr['arguments'].length;
allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
result = join(
'new',
generateExpression(expr.callee, {
precedence: Precedence.New,
allowIn: true,
allowCall: false,
allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
})
);
if (!allowUnparenthesizedNew || parentheses || len > 0) {
result.push('(');
for (i = 0; i < len; i += 1) {
result.push(generateExpression(expr['arguments'][i], {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
}));
if (i + 1 < len) {
result.push(',' + space);
}
}
result.push(')');
}
result = parenthesize(result, Precedence.New, precedence);
break;
case Syntax.MemberExpression:
result = [generateExpression(expr.object, {
precedence: Precedence.Call,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: false
})];
if (expr.computed) {
result.push('[', generateExpression(expr.property, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: allowCall
}), ']');
} else {
if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
if (result.indexOf('.') < 0) {
if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
result.push('.');
}
}
}
result.push('.' + expr.property.name);
}
result = parenthesize(result, Precedence.Member, precedence);
break;
case Syntax.PluckExpression:
result = [generateExpression(expr.object, {
precedence: Precedence.Call,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: false
})];
if (expr.computed) {
result.push('[', generateExpression(expr.property, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: allowCall
}), ']');
} else {
if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
if (result.indexOf('.') < 0) {
if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
result.push('.');
}
}
}
result.push('#' + expr.property.name);
}
result = parenthesize(result, Precedence.Member, precedence);
break;
case Syntax.UnaryExpression:
fragment = generateExpression(expr.argument, {
precedence: Precedence.Unary,
allowIn: true,
allowCall: true
});
if (space === '') {
result = join(expr.operator, fragment);
} else {
result = [expr.operator];
if (expr.operator.length > 2) {
// delete, void, typeof
// get `typeof []`, not `typeof[]`
result = join(result, fragment);
} else {
// Prevent inserting spaces between operator and argument if it is unnecessary
// like, `!cond`
leftSource = toSourceNode(result).toString();
leftChar = leftSource.charAt(leftSource.length - 1);
rightChar = fragment.toString().charAt(0);
if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
result.push(' ', fragment);
} else {
result.push(fragment);
}
}
}
result = parenthesize(result, Precedence.Unary, precedence);
break;
case Syntax.YieldExpression:
if (expr.delegate) {
result = 'yield*';
} else {
result = 'yield';
}
if (expr.argument) {
result = join(
result,
generateExpression(expr.argument, {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
})
);
}
break;
case Syntax.UpdateExpression:
if (expr.prefix) {
result = parenthesize(
[
expr.operator,
generateExpression(expr.argument, {
precedence: Precedence.Unary,
allowIn: true,
allowCall: true
})
],
Precedence.Unary,
precedence
);
} else {
result = parenthesize(
[
generateExpression(expr.argument, {
precedence: Precedence.Postfix,
allowIn: true,
allowCall: true
}),
expr.operator
],
Precedence.Postfix,
precedence
);
}
break;
case Syntax.FunctionExpression:
result = 'function';
if (expr.id) {
result += ' ' + expr.id.name;
} else {
result += space;
}
result = [result, generateFunctionBody(expr)];
break;
case Syntax.ArrayPattern:
case Syntax.ArrayExpression:
if (!expr.elements.length) {
result = '[]';
break;
}
multiline = expr.elements.length > 1;
result = ['[', multiline ? newline : ''];
withIndent(function (indent) {
for (i = 0, len = expr.elements.length; i < len; i += 1) {
if (!expr.elements[i]) {
if (multiline) {
result.push(indent);
}
if (i + 1 === len) {
result.push(',');
}
} else {
result.push(multiline ? indent : '', generateExpression(expr.elements[i], {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
}));
}
if (i + 1 < len) {
result.push(',' + (multiline ? newline : space));
}
}
});
if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
result.push(newline);
}
result.push(multiline ? base : '', ']');
break;
case Syntax.Property:
if (expr.kind === 'get' || expr.kind === 'set') {
result = [
expr.kind + ' ',
generateExpression(expr.key, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
generateFunctionBody(expr.value)
];
} else {
if (expr.shorthand) {
result = generateExpression(expr.key, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
});
} else if (expr.method) {
result = [];
if (expr.value.generator) {
result.push('*');
}
result.push(generateExpression(expr.key, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}), generateFunctionBody(expr.value));
} else {
result = [
generateExpression(expr.key, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
':' + space,
generateExpression(expr.value, {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
})
];
}
}
break;
case Syntax.ObjectExpression:
if (!expr.properties.length) {
result = '{}';
break;
}
multiline = expr.properties.length > 1;
withIndent(function (indent) {
fragment = generateExpression(expr.properties[0], {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
type: Syntax.Property
});
});
if (!multiline) {
// issues 4
// Do not transform from
// dejavu.Class.declare({
// method2: function () {}
// });
// to
// dejavu.Class.declare({method2: function () {
// }});
if (!hasLineTerminator(toSourceNode(fragment).toString())) {
result = [ '{', space, fragment, space, '}' ];
break;
}
}
withIndent(function (indent) {
result = [ '{', newline, indent, fragment ];
if (multiline) {
result.push(',' + newline);
for (i = 1, len = expr.properties.length; i < len; i += 1) {
result.push(indent, generateExpression(expr.properties[i], {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
type: Syntax.Property
}));
if (i + 1 < len) {
result.push(',' + newline);
}
}
}
});
if (!endsWithLineTerminator(toSourceNode(result).toString())) {
result.push(newline);
}
result.push(base, '}');
break;
case Syntax.ObjectPattern:
if (!expr.properties.length) {
result = '{}';
break;
}
multiline = false;
if (expr.properties.length === 1) {
property = expr.properties[0];
if (property.value.type !== Syntax.Identifier) {
multiline = true;
}
} else {
for (i = 0, len = expr.properties.length; i < len; i += 1) {
property = expr.properties[i];
if (!property.shorthand) {
multiline = true;
break;
}
}
}
result = ['{', multiline ? newline : '' ];
withIndent(function (indent) {
for (i = 0, len = expr.properties.length; i < len; i += 1) {
result.push(multiline ? indent : '', generateExpression(expr.properties[i], {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}));
if (i + 1 < len) {
result.push(',' + (multiline ? newline : space));
}
}
});
if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
result.push(newline);
}
result.push(multiline ? base : '', '}');
break;
case Syntax.ThisExpression:
result = 'this';
break;
case Syntax.Identifier:
result = expr.name;
break;
case Syntax.Literal:
if (expr.hasOwnProperty('raw') && parse) {
try {
raw = parse(expr.raw).body[0].expression;
if (raw.type === Syntax.Literal) {
if (raw.value === expr.value) {
result = expr.raw;
break;
}
}
} catch (e) {
// not use raw property
}
}
if (expr.value === null) {
result = 'null';
break;
}
if (typeof expr.value === 'string') {
result = escapeString(expr.value);
break;
}
if (typeof expr.value === 'number') {
result = generateNumber(expr.value);
break;
}
result = expr.value.toString();
break;
case Syntax.ComprehensionExpression:
result = [
'[',
generateExpression(expr.body, {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true
})
];
if (expr.blocks) {
for (i = 0, len = expr.blocks.length; i < len; i += 1) {
fragment = generateExpression(expr.blocks[i], {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
});
result = join(result, fragment);
}
}
if (expr.filter) {
result = join(result, 'if' + space);
fragment = generateExpression(expr.filter, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
});
if (extra.moz.parenthesizedComprehensionBlock) {
result = join(result, [ '(', fragment, ')' ]);
} else {
result = join(result, fragment);
}
}
result.push(']');
break;
case Syntax.ComprehensionBlock:
if (expr.left.type === Syntax.VariableDeclaration) {
fragment = [
expr.left.kind + ' ',
generateStatement(expr.left.declarations[0], {
allowIn: false
})
];
} else {
fragment = generateExpression(expr.left, {
precedence: Precedence.Call,
allowIn: true,
allowCall: true
});
}
fragment = join(fragment, expr.of ? 'of' : 'in');
fragment = join(fragment, generateExpression(expr.right, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}));
if (extra.moz.parenthesizedComprehensionBlock) {
result = [ 'for' + space + '(', fragment, ')' ];
} else {
result = join('for' + space, fragment);
}
break;
default:
throw new Error('Unknown expression type: ' + expr.type);
}
return toSourceNode(result, expr);
}
function generateStatement(stmt, option) {
var i, len, result, node, allowIn, functionBody, directiveContext, fragment, semicolon;
allowIn = true;
semicolon = ';';
functionBody = false;
directiveContext = false;
if (option) {
allowIn = option.allowIn === undefined || option.allowIn;
if (!semicolons && option.semicolonOptional === true) {
semicolon = '';
}
functionBody = option.functionBody;
directiveContext = option.directiveContext;
}
switch (stmt.type) {
case Syntax.BlockStatement:
result = ['{', newline];
withIndent(function () {
for (i = 0, len = stmt.body.length; i < len; i += 1) {
fragment = addIndent(generateStatement(stmt.body[i], {
semicolonOptional: i === len - 1,
directiveContext: functionBody
}));
result.push(fragment);
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
result.push(newline);
}
}
});
result.push(addIndent('}'));
break;
case Syntax.BreakStatement:
if (stmt.label) {
result = 'break ' + stmt.label.name + semicolon;
} else {
result = 'break' + semicolon;
}
break;
case Syntax.ContinueStatement:
if (stmt.label) {
result = 'continue ' + stmt.label.name + semicolon;
} else {
result = 'continue' + semicolon;
}
break;
case Syntax.DirectiveStatement:
if (stmt.raw) {
result = stmt.raw + semicolon;
} else {
result = escapeDirective(stmt.directive) + semicolon;
}
break;
case Syntax.DoWhileStatement:
// Because `do 42 while (cond)` is Syntax Error. We need semicolon.
result = join('do', maybeBlock(stmt.body));
result = maybeBlockSuffix(stmt.body, result);
result = join(result, [
'while' + space + '(',
generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')' + semicolon
]);
break;
case Syntax.CatchClause:
withIndent(function () {
result = [
'catch' + space + '(',
generateExpression(stmt.param, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')'
];
});
result.push(maybeBlock(stmt.body));
break;
case Syntax.DebuggerStatement:
result = 'debugger' + semicolon;
break;
case Syntax.EmptyStatement:
result = ';';
break;
case Syntax.ExpressionStatement:
result = [generateExpression(stmt.expression, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
})];
// 12.4 '{', 'function' is not allowed in this position.
// wrap expression with parentheses
if (result.toString().charAt(0) === '{' || (result.toString().slice(0, 8) === 'function' && " (".indexOf(result.toString().charAt(8)) >= 0) || (directive && directiveContext && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) {
result = ['(', result, ')' + semicolon];
} else {
result.push(semicolon);
}
break;
case Syntax.VariableDeclarator:
if (stmt.init) {
result = [
generateExpression(stmt.id, {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
}) + space + '=' + space,
generateExpression(stmt.init, {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true
})
];
} else {
result = stmt.id.name;
}
break;
case Syntax.VariableDeclaration:
result = [stmt.kind];
// special path for
// var x = function () {
// };
if (stmt.declarations.length === 1 && stmt.declarations[0].init &&
stmt.declarations[0].init.type === Syntax.FunctionExpression) {
result.push(' ', generateStatement(stmt.declarations[0], {
allowIn: allowIn
}));
} else {
// VariableDeclarator is typed as Statement,
// but joined with comma (not LineTerminator).
// So if comment is attached to target node, we should specialize.
withIndent(function () {
node = stmt.declarations[0];
if (extra.comment && node.leadingComments) {
result.push('\n', addIndent(generateStatement(node, {
allowIn: allowIn
})));
} else {
result.push(' ', generateStatement(node, {
allowIn: allowIn
}));
}
for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
node = stmt.declarations[i];
if (extra.comment && node.leadingComments) {
result.push(',' + newline, addIndent(generateStatement(node, {
allowIn: allowIn
})));
} else {
result.push(',' + space, generateStatement(node, {
allowIn: allowIn
}));
}
}
});
}
result.push(semicolon);
break;
case Syntax.ThrowStatement:
result = [join(
'throw',
generateExpression(stmt.argument, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
})
), semicolon];
break;
case Syntax.TryStatement:
result = ['try', maybeBlock(stmt.block)];
result = maybeBlockSuffix(stmt.block, result);
for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
result = join(result, generateStatement(stmt.handlers[i]));
if (stmt.finalizer || i + 1 !== len) {
result = maybeBlockSuffix(stmt.handlers[i].body, result);
}
}
if (stmt.finalizer) {
result = join(result, ['finally', maybeBlock(stmt.finalizer)]);
}
break;
case Syntax.SwitchStatement:
withIndent(function () {
result = [
'switch' + space + '(',
generateExpression(stmt.discriminant, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')' + space + '{' + newline
];
});
if (stmt.cases) {
for (i = 0, len = stmt.cases.length; i < len; i += 1) {
fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1}));
result.push(fragment);
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
result.push(newline);
}
}
}
result.push(addIndent('}'));
break;
case Syntax.SwitchCase:
withIndent(function () {
if (stmt.test) {
result = [
join('case', generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
})),
':'
];
} else {
result = ['default:'];
}
i = 0;
len = stmt.consequent.length;
if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
fragment = maybeBlock(stmt.consequent[0]);
result.push(fragment);
i = 1;
}
if (i !== len && !endsWithLineTerminator(toSourceNode(result).toString())) {
result.push(newline);
}
for (; i < len; i += 1) {
fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''}));
result.push(fragment);
if (i + 1 !== len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
result.push(newline);
}
}
});
break;
case Syntax.IfStatement:
withIndent(function () {
result = [
'if' + space + '(',
generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')'
];
});
if (stmt.alternate) {
result.push(maybeBlock(stmt.consequent));
result = maybeBlockSuffix(stmt.consequent, result);
if (stmt.alternate.type === Syntax.IfStatement) {
result = join(result, ['else ', generateStatement(stmt.alternate, {semicolonOptional: semicolon === ''})]);
} else {
result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === '')));
}
} else {
result.push(maybeBlock(stmt.consequent, semicolon === ''));
}
break;
case Syntax.ForStatement:
withIndent(function () {
result = ['for' + space + '('];
if (stmt.init) {
if (stmt.init.type === Syntax.VariableDeclaration) {
result.push(generateStatement(stmt.init, {allowIn: false}));
} else {
result.push(generateExpression(stmt.init, {
precedence: Precedence.Sequence,
allowIn: false,
allowCall: true
}), ';');
}
} else {
result.push(';');
}
if (stmt.test) {
result.push(space, generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}), ';');
} else {
result.push(';');
}
if (stmt.update) {
result.push(space, generateExpression(stmt.update, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}), ')');
} else {
result.push(')');
}
});
result.push(maybeBlock(stmt.body, semicolon === ''));
break;
case Syntax.ForInStatement:
result = ['for' + space + '('];
withIndent(function () {
if (stmt.left.type === Syntax.VariableDeclaration) {
withIndent(function () {
result.push(stmt.left.kind + ' ', generateStatement(stmt.left.declarations[0], {
allowIn: false
}));
});
} else {
result.push(generateExpression(stmt.left, {
precedence: Precedence.Call,
allowIn: true,
allowCall: true
}));
}
result = join(result, 'in');
result = [join(
result,
generateExpression(stmt.right, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
})
), ')'];
});
result.push(maybeBlock(stmt.body, semicolon === ''));
break;
case Syntax.LabeledStatement:
result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')];
break;
case Syntax.Program:
len = stmt.body.length;
result = [safeConcatenation && len > 0 ? '\n' : ''];
for (i = 0; i < len; i += 1) {
fragment = addIndent(
generateStatement(stmt.body[i], {
semicolonOptional: !safeConcatenation && i === len - 1,
directiveContext: true
})
);
result.push(fragment);
if (i + 1 < len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
result.push(newline);
}
}
break;
case Syntax.FunctionDeclaration:
result = [(stmt.generator && !extra.moz.starlessGenerator ? 'function* ' : 'function ') + stmt.id.name, generateFunctionBody(stmt)];
break;
case Syntax.ReturnStatement:
if (stmt.argument) {
result = [join(
'return',
generateExpression(stmt.argument, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
})
), semicolon];
} else {
result = ['return' + semicolon];
}
break;
case Syntax.WhileStatement:
withIndent(function () {
result = [
'while' + space + '(',
generateExpression(stmt.test, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')'
];
});
result.push(maybeBlock(stmt.body, semicolon === ''));
break;
case Syntax.WithStatement:
withIndent(function () {
result = [
'with' + space + '(',
generateExpression(stmt.object, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
}),
')'
];
});
result.push(maybeBlock(stmt.body, semicolon === ''));
break;
default:
throw new Error('Unknown statement type: ' + stmt.type);
}
// Attach comments
if (extra.comment) {
result = addCommentsToStatement(stmt, result);
}
fragment = toSourceNode(result).toString();
if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
result = toSourceNode(result).replaceRight(/\s+$/, '');
}
return toSourceNode(result, stmt);
}
function generate(node, options) {
var defaultOptions = getDefaultOptions(), result, pair;
if (options != null) {
// Obsolete options
//
// `options.indent`
// `options.base`
//
// Instead of them, we can use `option.format.indent`.
if (typeof options.indent === 'string') {
defaultOptions.format.indent.style = options.indent;
}
if (typeof options.base === 'number') {
defaultOptions.format.indent.base = options.base;
}
options = updateDeeply(defaultOptions, options);
indent = options.format.indent.style;
if (typeof options.base === 'string') {
base = options.base;
} else {
base = stringRepeat(indent, options.format.indent.base);
}
} else {
options = defaultOptions;
indent = options.format.indent.style;
base = stringRepeat(indent, options.format.indent.base);
}
json = options.format.json;
renumber = options.format.renumber;
hexadecimal = json ? false : options.format.hexadecimal;
quotes = json ? 'double' : options.format.quotes;
escapeless = options.format.escapeless;
if (options.format.compact) {
newline = space = indent = base = '';
} else {
newline = '\n';
space = ' ';
}
parentheses = options.format.parentheses;
semicolons = options.format.semicolons;
safeConcatenation = options.format.safeConcatenation;
directive = options.directive;
parse = json ? null : options.parse;
sourceMap = options.sourceMap;
extra = options;
if (sourceMap) {
if (!exports.browser) {
// We assume environment is node.js
// And prevent from including source-map by browserify
SourceNode = require('source-map').SourceNode;
} else {
SourceNode = global.sourceMap.SourceNode;
}
} else {
SourceNode = SourceNodeMock;
}
switch (node.type) {
case Syntax.BlockStatement:
case Syntax.BreakStatement:
case Syntax.CatchClause:
case Syntax.ContinueStatement:
case Syntax.DirectiveStatement:
case Syntax.DoWhileStatement:
case Syntax.DebuggerStatement:
case Syntax.EmptyStatement:
case Syntax.ExpressionStatement:
case Syntax.ForStatement:
case Syntax.ForInStatement:
case Syntax.FunctionDeclaration:
case Syntax.IfStatement:
case Syntax.LabeledStatement:
case Syntax.Program:
case Syntax.ReturnStatement:
case Syntax.SwitchStatement:
case Syntax.SwitchCase:
case Syntax.ThrowStatement:
case Syntax.TryStatement:
case Syntax.VariableDeclaration:
case Syntax.VariableDeclarator:
case Syntax.WhileStatement:
case Syntax.WithStatement:
result = generateStatement(node);
break;
case Syntax.AssignmentExpression:
case Syntax.ArrayExpression:
case Syntax.ArrayPattern:
case Syntax.BinaryExpression:
case Syntax.CallExpression:
case Syntax.ConditionalExpression:
case Syntax.FunctionExpression:
case Syntax.Identifier:
case Syntax.Literal:
case Syntax.LogicalExpression:
case Syntax.MemberExpression:
case Syntax.PluckExpression:
case Syntax.NewExpression:
case Syntax.ObjectExpression:
case Syntax.ObjectPattern:
case Syntax.Property:
case Syntax.SequenceExpression:
case Syntax.ThisExpression:
case Syntax.UnaryExpression:
case Syntax.UpdateExpression:
case Syntax.YieldExpression:
result = generateExpression(node, {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true
});
break;
default:
throw new Error('Unknown node type: ' + node.type);
}
if (!sourceMap) {
return result.toString();
}
pair = result.toStringWithSourceMap({
file: options.sourceMap,
sourceRoot: options.sourceMapRoot
});
if (options.sourceMapWithCode) {
return pair;
}
return pair.map.toString();
}
// simple visitor implementation
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
ArrayExpression: ['elements'],
ArrayPattern: ['elements'],
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
CallExpression: ['callee', 'arguments'],
CatchClause: ['param', 'body'],
ConditionalExpression: ['test', 'consequent', 'alternate'],
ContinueStatement: ['label'],
DirectiveStatement: [],
DoWhileStatement: ['body', 'test'],
DebuggerStatement: [],
EmptyStatement: [],
ExpressionStatement: ['expression'],
ForStatement: ['init', 'test', 'update', 'body'],
ForInStatement: ['left', 'right', 'body'],
FunctionDeclaration: ['id', 'params', 'body'],
FunctionExpression: ['id', 'params', 'body'],
Identifier: [],
IfStatement: ['test', 'consequent', 'alternate'],
Literal: [],
LabeledStatement: ['label', 'body'],
LogicalExpression: ['left', 'right'],
MemberExpression: ['object', 'property'],
PluckExpression: ['object', 'property'],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
ObjectPattern: ['properties'],
Program: ['body'],
Property: ['key', 'value'],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
ThisExpression: [],
ThrowStatement: ['argument'],
TryStatement: ['block', 'handlers', 'finalizer'],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
WithStatement: ['object', 'body'],
YieldExpression: ['argument']
};
VisitorOption = {
Break: 1,
Skip: 2
};
// based on LLVM libc++ upper_bound / lower_bound
// MIT License
function upperBound(array, func) {
var diff, len, i, current;
len = array.length;
i = 0;
while (len) {
diff = len >>> 1;
current = i + diff;
if (func(array[current])) {
len = diff;
} else {
i = current + 1;
len -= diff + 1;
}
}
return i;
}
function lowerBound(array, func) {
var diff, len, i, current;
len = array.length;
i = 0;
while (len) {
diff = len >>> 1;
current = i + diff;
if (func(array[current])) {
i = current + 1;
len -= diff + 1;
} else {
len = diff;
}
}
return i;
}
function extendCommentRange(comment, tokens) {
var target, token;
target = upperBound(tokens, function search(token) {
return token.range[0] > comment.range[0];
});
comment.extendedRange = [comment.range[0], comment.range[1]];
if (target !== tokens.length) {
comment.extendedRange[1] = tokens[target].range[0];
}
target -= 1;
if (target >= 0) {
if (target < tokens.length) {
comment.extendedRange[0] = tokens[target].range[1];
} else if (token.length) {
comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
}
}
return comment;
}
function attachComments(tree, providedComments, tokens) {
// At first, we should calculate extended comment ranges.
var comments = [], comment, len, i;
if (!tree.range) {
throw new Error('attachComments needs range information');
}
// tokens array is empty, we attach comments to tree as 'leadingComments'
if (!tokens.length) {
if (providedComments.length) {
for (i = 0, len = providedComments.length; i < len; i += 1) {
comment = deepCopy(providedComments[i]);
comment.extendedRange = [0, tree.range[0]];
comments.push(comment);
}
tree.leadingComments = comments;
}
return tree;
}
for (i = 0, len = providedComments.length; i < len; i += 1) {
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
}
// This is based on John Freeman's implementation.
traverse(tree, {
cursor: 0,
enter: function (node) {
var comment;
while (this.cursor < comments.length) {
comment = comments[this.cursor];
if (comment.extendedRange[1] > node.range[0]) {
break;
}
if (comment.extendedRange[1] === node.range[0]) {
if (!node.leadingComments) {
node.leadingComments = [];
}
node.leadingComments.push(comment);
comments.splice(this.cursor, 1);
} else {
this.cursor += 1;
}
}
// already out of owned node
if (this.cursor === comments.length) {
return VisitorOption.Break;
}
if (comments[this.cursor].extendedRange[0] > node.range[1]) {
return VisitorOption.Skip;
}
}
});
traverse(tree, {
cursor: 0,
leave: function (node) {
var comment;
while (this.cursor < comments.length) {
comment = comments[this.cursor];
if (node.range[1] < comment.extendedRange[0]) {
break;
}
if (node.range[1] === comment.extendedRange[0]) {
if (!node.trailingComments) {
node.trailingComments = [];
}
node.trailingComments.push(comment);
comments.splice(this.cursor, 1);
} else {
this.cursor += 1;
}
}
// already out of owned node
if (this.cursor === comments.length) {
return VisitorOption.Break;
}
if (comments[this.cursor].extendedRange[0] > node.range[1]) {
return VisitorOption.Skip;
}
}
});
return tree;
}
// Sync with package.json.
exports.version = '0.0.16-dev';
exports.generate = generate;
exports.attachComments = attachComments;
exports.browser = false;
}());
/* vim: set sw=4 ts=4 et tw=80 : */
});
require.define("/node_modules/estraverse/package.json",function(require,module,exports,__dirname,__filename,process,global){module.exports = {"main":"estraverse.js"}
});
require.define("/node_modules/estraverse/estraverse.js",function(require,module,exports,__dirname,__filename,process,global){/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*jslint bitwise:true */
/*global exports:true, define:true, window:true */
(function (factory) {
'use strict';
// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
// and plain browser loading,
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((window.estraverse = {}));
}
}(function (exports) {
'use strict';
var Syntax,
isArray,
VisitorOption,
VisitorKeys,
wrappers;
Syntax = {
AssignmentExpression: 'AssignmentExpression',
ArrayExpression: 'ArrayExpression',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DebuggerStatement: 'DebuggerStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
EmptyStatement: 'EmptyStatement',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
Identifier: 'Identifier',
IfStatement: 'IfStatement',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
PluckExpression: 'PluckExpression',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
Program: 'Program',
Property: 'Property',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement'
};
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray(array) {
return Object.prototype.toString.call(array) === '[object Array]';
};
}
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
ArrayExpression: ['elements'],
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
CallExpression: ['callee', 'arguments'],
CatchClause: ['param', 'body'],
ConditionalExpression: ['test', 'consequent', 'alternate'],
ContinueStatement: ['label'],
DebuggerStatement: [],
DirectiveStatement: [],
DoWhileStatement: ['body', 'test'],
EmptyStatement: [],
ExpressionStatement: ['expression'],
ForStatement: ['init', 'test', 'update', 'body'],
ForInStatement: ['left', 'right', 'body'],
FunctionDeclaration: ['id', 'params', 'body'],
FunctionExpression: ['id', 'params', 'body'],
Identifier: [],
IfStatement: ['test', 'consequent', 'alternate'],
Literal: [],
LabeledStatement: ['label', 'body'],
LogicalExpression: ['left', 'right'],
MemberExpression: ['object', 'property'],
PluckExpression: ['object', 'property'],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
Program: ['body'],
Property: ['key', 'value'],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
ThisExpression: [],
ThrowStatement: ['argument'],
TryStatement: ['block', 'handlers', 'finalizer'],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
WithStatement: ['object', 'body']
};
VisitorOption = {
Break: 1,
Skip: 2
};
wrappers = {
PropertyWrapper: 'Property'
};
function traverse(top, visitor) {
var worklist, leavelist, node, nodeType, ret, current, current2, candidates, candidate, marker = {};
worklist = [ top ];
leavelist = [ null ];
while (worklist.length) {
node = worklist.pop();
nodeType = node.type;
if (node === marker) {
node = leavelist.pop();
if (visitor.leave) {
ret = visitor.leave(node, leavelist[leavelist.length - 1]);
} else {
ret = undefined;
}
if (ret === VisitorOption.Break) {
return;
}
} else if (node) {
if (wrappers.hasOwnProperty(nodeType)) {
node = node.node;
nodeType = wrappers[nodeType];
}
if (visitor.enter) {
ret = visitor.enter(node, leavelist[leavelist.length - 1]);
} else {
ret = undefined;
}
if (ret === VisitorOption.Break) {
return;
}
worklist.push(marker);
leavelist.push(node);
if (ret !== VisitorOption.Skip) {
candidates = VisitorKeys[nodeType];
current = candidates.length;
while ((current -= 1) >= 0) {
candidate = node[candidates[current]];
if (candidate) {
if (isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (candidate[current2]) {
if(nodeType === Syntax.ObjectExpression && 'properties' === candidates[current] && null == candidates[current].type) {
worklist.push({type: 'PropertyWrapper', node: candidate[current2]});
} else {
worklist.push(candidate[current2]);
}
}
}
} else {
worklist.push(candidate);
}
}
}
}
}
}
}
function replace(top, visitor) {
var worklist, leavelist, node, nodeType, target, tuple, ret, current, current2, candidates, candidate, marker = {}, result;
result = {
top: top
};
tuple = [ top, result, 'top' ];
worklist = [ tuple ];
leavelist = [ tuple ];
function notify(v) {
ret = v;
}
while (worklist.length) {
tuple = worklist.pop();
if (tuple === marker) {
tuple = leavelist.pop();
ret = undefined;
if (visitor.leave) {
node = tuple[0];
target = visitor.leave(tuple[0], leavelist[leavelist.length - 1][0], notify);
if (target !== undefined) {
node = target;
}
tuple[1][tuple[2]] = node;
}
if (ret === VisitorOption.Break) {
return result.top;
}
} else if (tuple[0]) {
ret = undefined;
node = tuple[0];
nodeType = node.type;
if (wrappers.hasOwnProperty(nodeType)) {
tuple[0] = node = node.node;
nodeType = wrappers[nodeType];
}
if (visitor.enter) {
target = visitor.enter(tuple[0], leavelist[leavelist.length - 1][0], notify);
if (target !== undefined) {
node = target;
}
tuple[1][tuple[2]] = node;
tuple[0] = node;
}
if (ret === VisitorOption.Break) {
return result.top;
}
if (tuple[0]) {
worklist.push(marker);
leavelist.push(tuple);
if (ret !== VisitorOption.Skip) {
candidates = VisitorKeys[nodeType];
current = candidates.length;
while ((current -= 1) >= 0) {
candidate = node[candidates[current]];
if (candidate) {
if (isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (candidate[current2]) {
if(nodeType === Syntax.ObjectExpression && 'properties' === candidates[current] && null == candidates[current].type) {
worklist.push([{type: 'PropertyWrapper', node: candidate[current2]}, candidate, current2]);
} else {
worklist.push([candidate[current2], candidate, current2]);
}
}
}
} else {
worklist.push([candidate, node, candidates[current]]);
}
}
}
}
}
}
}
return result.top;
}
exports.version = '0.0.4';
exports.Syntax = Syntax;
exports.traverse = traverse;
exports.replace = replace;
exports.VisitorKeys = VisitorKeys;
exports.VisitorOption = VisitorOption;
}));
/* vim: set sw=4 ts=4 et tw=80 : */
});
require.define("/tools/entry-point.js",function(require,module,exports,__dirname,__filename,process,global){/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function () {
'use strict';
var escodegen;
escodegen = global.escodegen = require('../escodegen');
escodegen.browser = true;
}());
});
require("/tools/entry-point.js");
})();
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>My AngularJS App</title>
<link rel="stylesheet" href="radian.css"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-csv/0.71/jquery.csv-0.71.min.js"></script>
<script src="escodegen.browser.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.4/angular.js"></script>
<script src="radian.js"></script>
<script src="app.js"></script>
</head>
<body>
<plot height=500 aspect=2 zoom-x=0.25>
<lines x="[[dat.a]]" y="[[dat.b]]"></lines>
</plot>
<plot-data name="dat" format="csv" cols="a,b">
1,2.0264
2,2.0028
3,1.9965
4,1.9957
5,1.9998
6,2.0002
7,1.9769
8,1.9719
9,1.9595
10,1.9665
11,1.9752
12,1.9786
13,1.9752
14,1.9704
15,1.9595
16,1.9571
17,1.958
18,1.9496
19,1.9533
20,1.9526
21,1.954
22,1.9453
23,1.9331
24,1.9284
25,1.9361
26,1.9432
27,1.9581
28,1.9495
29,1.9494
30,1.9509
31,1.95
32,1.9563
33,1.9577
34,1.9574
35,1.9584
36,1.9661
37,1.9682
38,1.9714
39,1.977
40,1.9927
41,1.9911
42,1.9962
43,1.9958
44,1.9913
45,1.9907
46,1.9952
47,2.0054
48,2.022
49,2.0184
50,2.0287
51,2.026
52,2.0213
53,2.0143
54,2.0114
55,1.9975
56,2.0086
57,2.0067
58,2.009
59,2.0094
60,2.027
61,2.0317
62,2.0279
63,2.0369
64,2.0515
65,2.056
66,2.0525
67,2.0535
68,2.0613
69,2.0803
70,2.0815
71,2.092
72,2.0785
73,2.0739
74,2.0717
75,2.0563
76,2.0636
77,2.0448
78,2.0462
79,2.0458
80,2.0185
81,2.0178
82,2.0339
83,2.051
84,2.0402
85,2.0504
86,2.0594
87,2.0592
88,2.0475
89,2.0437
90,2.0319
91,2.0233
92,2.021
93,2.0374
94,2.0391
95,2.0374
96,2.0289
97,2.0207
98,2.0207
99,2.0358
100,2.0311
101,2.0282
102,2.0341
103,2.0378
104,2.0516
105,2.0508
106,2.0577
107,2.0566
108,2.047
109,2.0384
110,2.0355
111,2.0364
112,2.0435
113,2.0597
114,2.0486
115,2.0572
116,2.0579
117,2.0633
118,2.0817
119,2.0935
120,2.0955
121,2.1172
122,2.097
123,2.0995
124,2.1138
125,2.119
126,2.1409
127,2.154
128,2.1765
129,2.1915
130,2.1748
131,2.1602
132,2.177
133,2.1907
134,2.1838
135,2.1756
136,2.1938
137,2.2268
138,2.234
139,2.2575
140,2.2338
141,2.2638
142,2.2845
143,2.2794
144,2.2863
145,2.2695
146,2.2682
147,2.205
148,2.2211
149,2.2167
150,2.2199
151,2.1938
152,2.157
153,2.1615
154,2.1859
155,2.1992
156,2.1853
157,2.1847
158,2.1855
159,2.1808
160,2.171
161,2.1782
162,2.1695
163,2.1756
164,2.1867
165,2.1992
166,2.2188
167,2.223
168,2.2164
169,2.2175
170,2.2094
171,2.1977
172,2.207
173,2.213
174,2.2209
175,2.2176
176,2.2118
177,2.1847
178,2.1744
179,2.1415
180,2.1145
181,2.1285
182,2.112
183,2.132
184,2.133
185,2.123
186,2.1251
187,2.1475
188,2.1737
189,2.1745
190,2.1619
191,2.1642
192,2.163
193,2.1743
194,2.1678
195,2.143
196,2.15
197,2.1645
198,2.1661
199,2.1645
200,2.1583
201,2.1559
202,2.1463
203,2.1501
204,2.1563
205,2.1567
206,2.122
207,2.1205
208,2.1163
209,2.1059
210,2.1007
211,2.0653
212,2.0778
213,2.0794
214,2.065
215,2.0615
216,2.0691
217,2.0849
218,2.086
219,2.081
220,2.0855
221,2.0812
222,2.0812
223,2.1103
224,2.1295
225,2.1505
226,2.127
227,2.1419
228,2.131
229,2.1157
230,2.1112
231,2.1113
232,2.119
233,2.1364
234,2.1553
235,2.1714
236,2.1555
237,2.1265
238,2.1414
239,2.1263
240,2.1192
241,2.14
242,2.1503
243,2.1684
244,2.1555
245,2.1627
246,2.1567
247,2.1615
248,2.1602
249,2.1555
250,2.1665
251,2.2015
252,2.1873
253,2.1805
254,2.1845
255,2.1988
256,2.1945
257,2.2218
258,2.216
259,2.2245
260,2.2191
261,2.2172
262,2.2308
263,2.2465
264,2.2408
265,2.2358
266,2.2465
267,2.251
268,2.2414
269,2.2435
270,2.25
271,2.2436
272,2.23
273,2.2215
274,2.2285
275,2.2272
276,2.2335
277,2.2386
278,2.2465
279,2.2655
280,2.2625
281,2.2561
282,2.262
283,2.2532
284,2.2592
285,2.2688
286,2.2575
287,2.2585
288,2.239
289,2.247
290,2.2563
291,2.2542
292,2.249
293,2.2499
294,2.2597
295,2.2592
296,2.2483
297,2.2254
298,2.2012
299,2.221
300,2.2205
301,2.218
302,2.2175
303,2.2238
304,2.2297
305,2.2227
306,2.206
307,2.196
308,2.2018
309,2.1935
310,2.1986
311,2.1873
312,2.1868
313,2.1989
314,2.2048
315,2.1839
316,2.182
317,2.1742
318,2.1488
319,2.164
320,2.1467
321,2.166
322,2.1795
323,2.1901
324,2.2015
325,2.2264
326,2.1945
327,2.215
328,2.2215
329,2.2215
330,2.2213
331,2.228
332,2.236
333,2.247
334,2.2605
335,2.2553
336,2.234
337,2.2143
338,2.224
339,2.2252
340,2.2288
341,2.2225
342,2.2218
343,2.2085
344,2.2124
345,2.2101
346,2.2134
347,2.228
348,2.2148
349,2.2155
350,2.2158
351,2.2378
352,2.2275
353,2.2333
354,2.2605
355,2.2548
356,2.2537
357,2.2488
358,2.2453
359,2.214
360,2.2258
361,2.2375
362,2.2376
363,2.2575
364,2.239
365,2.2356
366,2.2375
367,2.2345
368,2.2438
369,2.234
370,2.2355
371,2.236
372,2.2415
373,2.2401
374,2.2415
375,2.2355
376,2.247
377,2.2565
378,2.2655
379,2.269
380,2.2721
381,2.2605
382,2.272
383,2.2915
384,2.296
385,2.2929
386,2.2952
387,2.299
388,2.3005
389,2.3025
390,2.3003
391,2.305
392,2.2976
393,2.304
394,2.3092
395,2.3091
396,2.3252
397,2.3199
398,2.3145
399,2.3043
400,2.2903
401,2.2763
402,2.2675
403,2.274
404,2.285
405,2.2908
406,2.2892
407,2.293
408,2.2948
409,2.2965
410,2.3005
411,2.3002
412,2.3007
413,2.2977
414,2.2938
415,2.2975
416,2.3
417,2.3008
418,2.3148
419,2.331
420,2.3303
421,2.3375
422,2.349
423,2.3557
424,2.3535
425,2.3593
426,2.3586
427,2.3639
428,2.3543
429,2.3599
430,2.3689
431,2.3746
432,2.3602
433,2.3569
434,2.3579
435,2.3569
436,2.359
437,2.371
438,2.3715
439,2.3702
440,2.3701
441,2.3745
442,2.378
443,2.3773
444,2.3756
445,2.3734
446,2.3765
447,2.3777
448,2.3725
449,2.3722
450,2.3794
451,2.3759
452,2.3837
453,2.3816
454,2.3827
455,2.3878
456,2.3912
457,2.3995
458,2.4152
459,2.4107
460,2.4218
461,2.4275
462,2.4225
463,2.4175
464,2.426
465,2.4235
466,2.4223
467,2.4305
468,2.4459
469,2.4385
470,2.4408
471,2.4118
472,2.3883
473,2.3867
474,2.3898
475,2.415
476,2.3985
477,2.4
478,2.4032
479,2.387
480,2.4007
481,2.383
482,2.376
483,2.3747
484,2.3952
485,2.3328
486,2.3268
487,2.3867
488,2.3785
489,2.376
490,2.375
491,2.3755
492,2.3782
493,2.3845
494,2.3894
495,2.3727
496,2.3777
497,2.3817
498,2.3715
499,2.3672
500,2.371
501,2.363
502,2.386
503,2.3952
504,2.3962
505,2.396
506,2.4145
507,2.4165
508,2.4045
509,2.4315
510,2.4412
511,2.4368
512,2.4322
513,2.434
514,2.4339
515,2.4324
516,2.4372
517,2.4458
518,2.4475
519,2.4632
520,2.468
521,2.4745
522,2.465
523,2.4695
524,2.472
525,2.4711
526,2.4672
527,2.4575
528,2.4375
529,2.4095
530,2.4015
531,2.425
532,2.4145
533,2.4054
534,2.4115
535,2.4102
536,2.4177
537,2.408
538,2.3855
539,2.357
540,2.3535
541,2.3645
542,2.358
543,2.394
544,2.3362
545,2.3147
546,2.3087
547,2.3087
548,2.2867
549,2.268
550,2.2837
551,2.276
552,2.2825
553,2.2722
554,2.2867
555,2.2857
556,2.279
557,2.2764
558,2.2767
559,2.281
560,2.2977
561,2.3107
562,2.314
563,2.311
564,2.2965
565,2.3137
566,2.3083
567,2.3097
568,2.2835
569,2.291
570,2.2905
571,2.2822
572,2.2792
573,2.2545
574,2.2347
575,2.2485
576,2.264
577,2.253
578,2.2495
579,2.2358
580,2.2447
581,2.2302
582,2.2232
583,2.2292
584,2.2462
585,2.2512
586,2.2367
587,2.2347
588,2.2256
589,2.2182
590,2.2192
591,2.2225
592,2.2157
593,2.222
594,2.2137
595,2.2192
596,2.2052
597,2.1937
598,2.1845
599,2.1705
600,2.1725
601,2.174
602,2.1685
603,2.163
604,2.1607
605,2.161
606,2.1477
607,2.1327
608,2.1382
609,2.1382
610,2.1243
611,2.1122
612,2.0825
613,2.0112
614,1.9732
615,1.9855
616,1.9897
617,2.0122
618,2.0004
619,2.0054
620,2.038
621,2.0467
622,2.0502
623,2.031
624,2.0262
625,2.0417
626,2.0524
627,2.0385
628,2.0105
629,2.0094
630,2
631,1.9941
632,1.9657
633,1.948
634,1.9507
635,1.9435
636,1.9537
637,1.9449
638,1.9358
639,1.9507
640,1.9504
641,1.9167
642,1.9355
643,1.936
644,1.9315
645,1.922
646,1.9035
647,1.9137
648,1.9124
649,1.9147
650,1.9227
651,1.9115
652,1.906
653,1.8997
654,1.8665
655,1.8718
656,1.8677
657,1.8595
658,1.858
659,1.829
660,1.832
661,1.8885
662,1.8705
663,1.8732
664,1.887
665,1.8915
666,1.8945
667,1.9264
668,1.9305
669,1.937
670,1.8967
671,1.9077
672,1.9072
673,1.913
674,1.9069
675,1.9088
676,1.9163
677,1.9137
678,1.888
679,1.8688
680,1.8485
681,1.8725
682,1.8505
683,1.842
684,1.881
685,1.8922
686,1.8939
687,1.87
688,1.8737
689,1.871
690,1.8547
691,1.807
692,1.8222
693,1.8047
694,1.8177
695,1.8317
696,1.8525
697,1.845
698,1.8584
699,1.8482
700,1.8672
701,1.9022
702,1.9117
703,1.8902
704,1.8715
705,1.8702
706,1.8705
707,1.8387
708,1.8557
709,1.8399
710,1.831
711,1.824
712,1.8295
713,1.8125
714,1.8225
715,1.83
716,1.8448
717,1.8532
718,1.8742
719,1.8748
720,1.8783
721,1.8783
722,1.875
723,1.8875
724,1.8703
725,1.879
726,1.8865
727,1.9055
728,1.914
729,1.8837
730,1.89
731,1.8997
732,1.8935
733,1.899
734,1.895
735,1.957
736,1.9193
737,1.937
738,1.938
739,1.927
740,1.932
741,1.9223
742,1.9338
743,1.9297
744,1.9149
745,1.9068
746,1.881
747,1.869
748,1.848
749,1.871
750,1.8765
751,1.8735
752,1.8635
753,1.8675
754,1.8746
755,1.8814
756,1.8795
757,1.8785
758,1.8948
759,1.901
760,1.914
761,1.9055
762,1.912
763,1.9062
764,1.913
765,1.8865
766,1.877
767,1.8695
768,1.8533
769,1.868
770,1.8727
771,1.8965
772,1.8945
773,1.9017
774,1.8902
775,1.8747
776,1.8817
777,1.8893
778,1.8882
779,1.8945
780,1.8855
781,1.8875
782,1.8823
783,1.8806
784,1.8773
785,1.8819
786,1.8714
787,1.8751
788,1.877
789,1.868
790,1.8647
791,1.8655
792,1.8708
793,1.8688
794,1.8698
795,1.868
796,1.8545
797,1.848
798,1.852
799,1.8442
800,1.841
801,1.8382
802,1.8453
803,1.8474
804,1.8587
805,1.8458
806,1.8335
807,1.834
808,1.837
809,1.8271
810,1.8318
811,1.8338
812,1.835
813,1.8344
814,1.8292
815,1.8273
816,1.8267
817,1.831
818,1.8272
819,1.815
820,1.811
821,1.8124
822,1.8125
823,1.8124
824,1.8167
825,1.7953
826,1.7695
827,1.7895
828,1.7835
829,1.788
830,1.7904
831,1.7793
832,1.7855
833,1.7818
834,1.792
835,1.7905
836,1.7955
837,1.7917
838,1.7922
839,1.792
840,1.802
841,1.8135
842,1.8146
843,1.825
844,1.8254
845,1.8438
846,1.8475
847,1.8556
848,1.8518
849,1.86
850,1.8506
851,1.844
852,1.8427
853,1.8285
854,1.8177
855,1.7945
856,1.8085
857,1.8225
858,1.8236
859,1.818
860,1.8167
861,1.813
862,1.8098
863,1.8145
864,1.8241
865,1.826
866,1.823
867,1.8175
868,1.8119
869,1.798
870,1.8061
871,1.8025
872,1.804
873,1.7992
874,1.7892
875,1.7875
876,1.7715
877,1.789
878,1.7805
879,1.7898
880,1.777
881,1.7718
882,1.7785
883,1.789
884,1.7817
885,1.7812
886,1.7788
887,1.7727
888,1.7612
889,1.7622
890,1.7727
891,1.776
892,1.769
893,1.7645
894,1.7603
895,1.7585
896,1.775
897,1.7665
898,1.7781
899,1.779
900,1.7905
901,1.7935
902,1.7901
903,1.7851
904,1.781
905,1.7772
906,1.7805
907,1.7861
908,1.7702
909,1.756
910,1.752
911,1.7365
912,1.7485
913,1.7362
914,1.7377
915,1.7395
916,1.7353
917,1.736
918,1.752
919,1.7451
920,1.7617
921,1.7658
922,1.7808
923,1.797
924,1.7955
925,1.7737
926,1.7503
927,1.7565
928,1.768
929,1.7681
930,1.7576
931,1.7753
932,1.5914
933,1.7547
934,1.7507
935,1.7428
936,1.7466
937,1.7487
938,1.7413
939,1.7493
940,1.75
941,1.7446
942,1.7476
943,1.7437
944,1.7373
945,1.7327
946,1.7289
947,1.7276
948,1.7262
949,1.7283
950,1.7157
951,1.7172
952,1.7243
953,1.729
954,1.74
955,1.7388
956,1.7436
957,1.7352
958,1.7302
959,1.723
960,1.7285
961,1.7258
962,1.7134
963,1.7123
964,1.7147
965,1.7001
966,1.7057
967,1.7028
968,1.6846
969,1.6943
970,1.6957
971,1.6997
972,1.6959
973,1.6874
974,1.6821
975,1.6727
976,1.6762
977,1.6837
978,1.6743
979,1.6704
980,1.6541
981,1.6477
982,1.62
983,1.6216
984,1.6396
985,1.6097
986,1.6086
987,1.6134
988,1.5947
989,1.6003
990,1.6099
991,1.6204
992,1.6392
993,1.6411
994,1.6465
995,1.6315
996,1.6264
997,1.6218
998,1.6098
999,1.6143
1000,1.603
1001,1.6171
1002,1.6107
1003,1.6172
1004,1.612
1005,1.6092
1006,1.5981
1007,1.601
1008,1.585
1009,1.5953
1010,1.6155
1011,1.613
1012,1.6085
1013,1.6125
1014,1.6095
1015,1.594
1016,1.587
1017,1.5741
1018,1.542
1019,1.5493
1020,1.552
1021,1.555
1022,1.5655
1023,1.55
1024,1.5473
1025,1.545
1026,1.55
1027,1.5145
1028,1.518
1029,1.5265
1030,1.5193
1031,1.5172
1032,1.5054
1033,1.506
1034,1.503
1035,1.5048
1036,1.5035
1037,1.5254
1038,1.5285
1039,1.5321
1040,1.5314
1041,1.533
1042,1.525
1043,1.5345
1044,1.533
1045,1.5313
1046,1.5297
1047,1.522
1048,1.5017
1049,1.5043
1050,1.5115
1051,1.5114
1052,1.4955
1053,1.4875
1054,1.4861
1055,1.4922
1056,1.4943
1057,1.5015
1058,1.4873
1059,1.4856
1060,1.4968
1061,1.4848
1062,1.4937
1063,1.5057
1064,1.4985
1065,1.4973
1066,1.4799
1067,1.4629
1068,1.4618
1069,1.4539
1070,1.455
1071,1.4526
1072,1.4454
1073,1.4461
1074,1.4551
1075,1.4761
1076,1.4983
1077,1.5129
1078,1.5023
1079,1.4984
1080,1.5201
1081,1.5289
1082,1.5395
1083,1.5291
1084,1.5372
1085,1.5491
1086,1.5493
1087,1.5454
1088,1.5373
1089,1.541
1090,1.559
1091,1.5647
1092,1.5576
1093,1.5517
1094,1.5515
1095,1.5677
1096,1.5732
1097,1.5712
1098,1.5678
1099,1.5615
1100,1.5525
1101,1.554
1102,1.5555
1103,1.5518
1104,1.5449
1105,1.5412
1106,1.5595
1107,1.5439
1108,1.5458
1109,1.543
1110,1.5612
1111,1.5764
1112,1.5892
1113,1.5904
1114,1.5996
1115,1.5844
1116,1.5768
1117,1.5549
1118,1.5707
1119,1.5695
1120,1.5707
1121,1.5828
1122,1.5776
1123,1.5538
1124,1.5336
1125,1.5239
1126,1.5333
1127,1.5265
1128,1.5334
1129,1.5369
1130,1.5343
1131,1.5439
1132,1.5507
1133,1.5482
1134,1.5347
1135,1.5311
1136,1.5372
1137,1.5352
1138,1.5334
1139,1.529
1140,1.5412
1141,1.5437
1142,1.5426
1143,1.5377
1144,1.5342
1145,1.5358
1146,1.5335
1147,1.5198
1148,1.5254
1149,1.5238
1150,1.5298
1151,1.5295
1152,1.5236
1153,1.5224
1154,1.5302
1155,1.5308
1156,1.5307
1157,1.5254
1158,1.5185
1159,1.5158
1160,1.5115
1161,1.4961
1162,1.4926
1163,1.4941
1164,1.4996
1165,1.4917
1166,1.4874
1167,1.492
1168,1.4954
1169,1.5094
1170,1.5217
1171,1.5278
1172,1.5251
1173,1.5323
1174,1.5343
1175,1.5288
1176,1.5109
1177,1.5031
1178,1.5036
1179,1.5017
1180,1.5077
1181,1.5043
1182,1.5093
1183,1.5078
1184,1.4943
1185,1.4988
1186,1.5021
1187,1.5079
1188,1.4998
1189,1.4972
1190,1.5011
1191,1.505
1192,1.5125
1193,1.5174
1194,1.512
1195,1.5055
1196,1.5081
1197,1.5107
1198,1.5033
1199,1.5047
1200,1.5056
1201,1.4992
1202,1.4877
1203,1.4801
1204,1.4888
1205,1.4954
1206,1.5105
1207,1.5172
1208,1.513
1209,1.5119
1210,1.5055
1211,1.5033
1212,1.5079
1213,1.5066
1214,1.5035
1215,1.5041
1216,1.5065
1217,1.5042
1218,1.5056
1219,1.5033
1220,1.5008
1221,1.503
1222,1.5013
1223,1.5018
1224,1.4951
1225,1.4983
1226,1.4956
1227,1.4976
1228,1.4991
1229,1.4966
1230,1.499
1231,1.4961
1232,1.497
1233,1.4957
1234,1.4975
1235,1.4907
1236,1.482
1237,1.4793
1238,1.4802
1239,1.4788
1240,1.4764
1241,1.4695
1242,1.4716
1243,1.4671
1244,1.4759
1245,1.4695
1246,1.4673
1247,1.4624
1248,1.4607
1249,1.4593
1250,1.4537
1251,1.4494
1252,1.4464
1253,1.4341
1254,1.4315
1255,1.4333
1256,1.4286
1257,1.4302
1258,1.4303
1259,1.4339
1260,1.4367
1261,1.4432
1262,1.4442
1263,1.4562
1264,1.4615
1265,1.4411
1266,1.4261
1267,1.4219
1268,1.4166
1269,1.4089
1270,1.4142
1271,1.4041
1272,1.4043
1273,1.4181
1274,1.424
1275,1.4232
1276,1.4153
1277,1.4283
1278,1.41
1279,1.4174
1280,1.4056
1281,1.41
1282,1.4157
1283,1.4118
1284,1.4131
1285,1.4106
1286,1.4145
1287,1.4282
1288,1.4309
1289,1.4354
1290,1.4225
1291,1.4219
1292,1.4322
1293,1.424
1294,1.4282
1295,1.4325
1296,1.4465
1297,1.4581
1298,1.4627
1299,1.4608
1300,1.4628
1301,1.4708
1302,1.4798
1303,1.4847
1304,1.4851
1305,1.5123
1306,1.5121
1307,1.5031
1308,1.5088
1309,1.5074
1310,1.5048
1311,1.5037
1312,1.4941
1313,1.4879
1314,1.485
1315,1.4905
1316,1.5048
1317,1.4876
1318,1.4783
1319,1.4731
1320,1.4705
1321,1.4634
1322,1.4615
1323,1.4695
1324,1.4724
1325,1.4793
1326,1.4759
1327,1.4807
1328,1.4717
1329,1.469
1330,1.4596
1331,1.4646
1332,1.4675
1333,1.4607
1334,1.4665
1335,1.4647
1336,1.4732
1337,1.4691
1338,1.4589
1339,1.4555
1340,1.4546
1341,1.4512
1342,1.4544
1343,1.4444
1344,1.4453
1345,1.4387
1346,1.438
1347,1.4286
1348,1.4282
1349,1.4305
1350,1.433
1351,1.4422
1352,1.4145
1353,1.4171
1354,1.4189
1355,1.421
1356,1.4239
1357,1.4232
1358,1.4296
1359,1.4338
1360,1.4244
1361,1.4299
1362,1.4263
1363,1.4215
1364,1.4123
1365,1.4183
1366,1.4174
1367,1.42
1368,1.4197
1369,1.4277
1370,1.4359
1371,1.432
1372,1.4352
1373,1.4363
1374,1.4329
1375,1.4342
1376,1.4257
1377,1.4243
1378,1.424
1379,1.4147
1380,1.4131
1381,1.4132
1382,1.4064
1383,1.4036
1384,1.4033
1385,1.3902
1386,1.3915
1387,1.3859
1388,1.387
1389,1.394
1390,1.3872
1391,1.3735
1392,1.3731
1393,1.3609
1394,1.3515
1395,1.3322
1396,1.327
1397,1.3282
1398,1.3266
1399,1.3417
1400,1.3447
1401,1.3422
1402,1.3274
1403,1.3368
1404,1.3401
1405,1.3333
1406,1.3374
1407,1.3454
1408,1.344
1409,1.3195
1410,1.3162
1411,1.3203
1412,1.309
1413,1.321
1414,1.337
1415,1.3355
1416,1.3202
1417,1.3279
1418,1.3316
1419,1.3332
1420,1.327
1421,1.3509
1422,1.3449
1423,1.3315
1424,1.3461
1425,1.3423
1426,1.3358
1427,1.33
1428,1.3305
1429,1.3285
1430,1.3332
1431,1.3372
1432,1.3346
1433,1.3338
1434,1.3258
1435,1.3149
1436,1.3072
1437,1.3058
1438,1.3006
1439,1.2965
1440,1.298
1441,1.3022
1442,1.2903
1443,1.2847
1444,1.2614
1445,1.2438
1446,1.2543
1447,1.2357
1448,1.251
1449,1.264
1450,1.2507
1451,1.2448
1452,1.263
1453,1.2532
1454,1.2541
1455,1.2576
1456,1.2671
1457,1.259
1458,1.251
1459,1.2543
1460,1.2459
1461,1.2398
1462,1.2402
1463,1.2445
1464,1.2226
1465,1.2174
1466,1.2145
1467,1.1931
1468,1.1962
1469,1.2052
1470,1.2157
1471,1.2272
1472,1.232
1473,1.2277
1474,1.2178
1475,1.2181
1476,1.2217
1477,1.2311
1478,1.2589
1479,1.2688
1480,1.2702
1481,1.28
1482,1.2762
1483,1.2712
1484,1.273
1485,1.2834
1486,1.2711
1487,1.2729
1488,1.2709
1489,1.2584
1490,1.2547
1491,1.2316
1492,1.2351
1493,1.2235
1494,1.202
1495,1.2119
1496,1.1994
1497,1.2005
1498,1.2073
1499,1.198
1500,1.2109
1501,1.2096
1502,1.2093
1503,1.2088
1504,1.2109
1505,1.2076
1506,1.2032
1507,1.1946
1508,1.1926
1509,1.1921
1510,1.1835
1511,1.1747
1512,1.168
1513,1.1692
1514,1.1747
1515,1.1643
1516,1.1617
1517,1.1547
1518,1.1395
1519,1.1443
1520,1.1461
1521,1.1363
1522,1.1426
1523,1.1334
1524,1.1231
1525,1.117
1526,1.094
1527,1.1016
1528,1.105
1529,1.1034
1530,1.1038
1531,1.1079
1532,1.1064
1533,1.0908
1534,1.0937
1535,1.089
1536,1.0782
1537,1.0872
1538,1.1025
1539,1.108
1540,1.1065
1541,1.0914
1542,1.0887
1543,1.0859
1544,1.0937
1545,1.0956
1546,1.0705
1547,1.065
1548,1.0624
1549,1.0688
1550,1.0823
1551,1.071
1552,1.0726
1553,1.0658
1554,1.0685
1555,1.0543
1556,1.032
1557,1.0198
1558,1.0725
1559,1.0645
1560,1.0537
1561,1.0546
1562,1.0451
1563,1.0378
1564,1.0495
1565,1.0551
1566,1.0729
1567,1.0765
1568,1.0676
1569,1.0671
1570,1.0722
1571,1.0936
1572,1.1265
1573,1.1257
1574,1.177
1575,1.1582
1576,1.1563
1577,1.1617
1578,1.2089
1579,1.2107
1580,1.2132
1581,1.206
1582,1.1921
1583,1.2008
1584,1.175
1585,1.18
1586,1.2005
1587,1.2251
1588,1.2268
1589,1.2599
1590,1.2562
1591,1.2593
1592,1.271
1593,1.2697
1594,1.2614
1595,1.2385
1596,1.1985
1597,1.1812
1598,1.19
1599,1.2014
1600,1.2137
1601,1.1962
1602,1.1942
1603,1.182
1604,1.1773
1605,1.1795
1606,1.2014
1607,1.2049
1608,1.2212
1609,1.2363
1610,1.2298
1611,1.2196
1612,1.227
1613,1.2483
1614,1.2318
1615,1.2309
1616,1.2203
1617,1.224
1618,1.2131
1619,1.2239
1620,1.2343
1621,1.2461
1622,1.2527
1623,1.2425
1624,1.218
1625,1.2297
1626,1.228
1627,1.2192
1628,1.2251
1629,1.2235
1630,1.2261
1631,1.2381
1632,1.2342
1633,1.2516
1634,1.2681
1635,1.2362
1636,1.2397
1637,1.2474
1638,1.2477
1639,1.2568
1640,1.2536
1641,1.27
1642,1.2656
1643,1.2595
1644,1.269
1645,1.2746
1646,1.285
1647,1.291
1648,1.3225
1649,1.3407
1650,1.3363
1651,1.3506
1652,1.352
1653,1.3527
1654,1.3797
1655,1.3725
1656,1.369
1657,1.3583
1658,1.384
1659,1.3697
1660,1.3732
1661,1.3756
1662,1.4044
1663,1.4035
1664,1.3923
1665,1.358
1666,1.3401
1667,1.3416
1668,1.3195
1669,1.32
1670,1.3265
1671,1.3271
1672,1.3492
1673,1.3656
1674,1.3566
1675,1.366
1676,1.3771
1677,1.3747
1678,1.3617
1679,1.36
1680,1.3827
1681,1.376
1682,1.3638
1683,1.374
1684,1.3688
1685,1.3664
1686,1.3544
1687,1.3417
1688,1.3418
1689,1.3415
1690,1.3028
1691,1.2807
1692,1.2848
1693,1.279
1694,1.2867
1695,1.3122
1696,1.3078
1697,1.3205
1698,1.3148
1699,1.3119
1700,1.3414
1701,1.4055
1702,1.3978
1703,1.397
1704,1.4093
1705,1.38
1706,1.3779
1707,1.3747
1708,1.3835
1709,1.3911
1710,1.3873
1711,1.3903
1712,1.3861
1713,1.387
1714,1.3834
1715,1.3808
1716,1.3857
1717,1.3845
1718,1.3805
1719,1.3867
1720,1.395
1721,1.4007
1722,1.4002
1723,1.4003
1724,1.3914
1725,1.3914
1726,1.3938
1727,1.4023
1728,1.4055
1729,1.4086
1730,1.3981
1731,1.4016
1732,1.3981
1733,1.3975
1734,1.3825
1735,1.381
1736,1.381
1737,1.3764
1738,1.3859
1739,1.388
1740,1.3862
1741,1.3877
1742,1.3967
1743,1.3954
1744,1.4025
1745,1.4128
1746,1.4257
1747,1.4289
1748,1.4336
1749,1.4402
1750,1.4536
1751,1.4525
1752,1.4471
1753,1.4487
1754,1.4415
1755,1.4408
1756,1.4245
1757,1.3942
1758,1.3718
1759,1.3945
1760,1.3933
1761,1.3914
1762,1.3915
1763,1.378
1764,1.3767
1765,1.3788
1766,1.385
1767,1.3787
1768,1.39
1769,1.395
1770,1.3995
1771,1.3978
1772,1.3941
1773,1.3952
1774,1.39
1775,1.389
1776,1.389
1777,1.4042
1778,1.3795
1779,1.3829
1780,1.3867
1781,1.3858
1782,1.3827
1783,1.357
1784,1.3509
1785,1.338
1786,1.3172
1787,1.332
1788,1.3292
1789,1.354
1790,1.3471
1791,1.3569
1792,1.3549
1793,1.3316
1794,1.3233
1795,1.3393
1796,1.3489
1797,1.3502
1798,1.3536
1799,1.3605
1800,1.3609
1801,1.3606
1802,1.3639
1803,1.3675
1804,1.3758
1805,1.4117
1806,1.4043
1807,1.3983
1808,1.413
1809,1.4436
1810,1.4427
1811,1.4339
1812,1.401
1813,1.3872
1814,1.4119
1815,1.4094
1816,1.4063
1817,1.4125
1818,1.3935
1819,1.416
1820,1.4279
1821,1.4119
1822,1.4213
1823,1.4216
1824,1.428
1825,1.4357
1826,1.4513
1827,1.4675
1828,1.4484
1829,1.418
1830,1.435
1831,1.4412
1832,1.4318
1833,1.4334
1834,1.4226
1835,1.41
1836,1.4151
1837,1.4427
1838,1.4288
1839,1.4284
1840,1.4465
1841,1.4458
1842,1.4413
1843,1.4677
1844,1.4888
1845,1.4804
1846,1.4733
1847,1.4772
1848,1.4885
1849,1.4989
1850,1.4954
1851,1.5151
1852,1.5165
1853,1.5164
1854,1.4941
1855,1.4897
1856,1.4951
1857,1.499
1858,1.5112
1859,1.4998
1860,1.5104
1861,1.5118
1862,1.4994
1863,1.5019
1864,1.4891
1865,1.4843
1866,1.4852
1867,1.4821
1868,1.4626
1869,1.459
1870,1.4669
1871,1.472
1872,1.4686
1873,1.4434
1874,1.4472
1875,1.4686
1876,1.4617
1877,1.4621
1878,1.4824
1879,1.4711
1880,1.4859
1881,1.5026
1882,1.498
1883,1.4919
1884,1.4898
1885,1.4749
1886,1.4673
1887,1.4699
1888,1.4668
1889,1.4579
1890,1.4781
1891,1.4884
1892,1.4824
1893,1.4897
1894,1.4939
1895,1.5051
1896,1.4997
1897,1.5051
1898,1.5012
1899,1.4964
1900,1.4947
1901,1.4838
1902,1.4732
1903,1.465
1904,1.439
1905,1.4525
1906,1.4628
1907,1.4697
1908,1.4503
1909,1.4537
1910,1.4467
1911,1.4446
1912,1.4465
1913,1.4431
1914,1.4258
1915,1.4408
1916,1.4447
1917,1.4485
1918,1.4426
1919,1.4225
1920,1.4401
1921,1.4352
1922,1.4309
1923,1.4291
1924,1.4396
1925,1.4395
1926,1.4409
1927,1.4444
1928,1.4492
1929,1.4479
1930,1.4585
1931,1.4572
1932,1.4517
1933,1.4437
1934,1.4347
1935,1.4365
1936,1.4285
1937,1.4355
1938,1.436
1939,1.4369
1940,1.4466
1941,1.4525
1942,1.447
1943,1.4381
1944,1.4349
1945,1.4321
1946,1.4265
1947,1.4239
1948,1.4322
1949,1.4278
1950,1.4201
1951,1.4127
1952,1.419
1953,1.4006
1954,1.397
1955,1.3895
1956,1.371
1957,1.373
1958,1.367
1959,1.3869
1960,1.3841
1961,1.3706
1962,1.3795
1963,1.3795
1964,1.3745
1965,1.3537
1966,1.3609
1967,1.371
1968,1.3716
1969,1.3722
1970,1.3719
1971,1.3739
1972,1.3633
1973,1.3667
1974,1.3736
1975,1.3712
1976,1.3591
1977,1.3477
1978,1.3462
1979,1.35
1980,1.351
1981,1.3376
1982,1.3455
1983,1.3508
1984,1.3521
1985,1.36
1986,1.3716
1987,1.3681
1988,1.3764
1989,1.3777
1990,1.3645
1991,1.358
1992,1.3661
1993,1.3644
1994,1.359
1995,1.3567
1996,1.3444
1997,1.3464
1998,1.3523
1999,1.357
2000,1.3654
2001,1.3622
2002,1.3701
2003,1.369
2004,1.3646
2005,1.3643
2006,1.3644
2007,1.3637
2008,1.3515
2009,1.3539
2010,1.3577
2011,1.3559
2012,1.3621
2013,1.37
2014,1.3672
2015,1.3659
2016,1.3643
2017,1.3691
2018,1.3795
2019,1.3858
2020,1.394
2021,1.4047
2022,1.404
2023,1.4212
2024,1.4316
2025,1.4094
2026,1.4134
2027,1.4063
2028,1.4079
2029,1.412
2030,1.4271
2031,1.4285
2032,1.4383
2033,1.4424
2034,1.4554
2035,1.4731
2036,1.4595
2037,1.4583
2038,1.472
2039,1.4634
2040,1.4632
2041,1.4663
2042,1.4809
2043,1.4762
2044,1.4524
2045,1.4553
2046,1.4653
2047,1.4618
2048,1.4585
2049,1.4498
2050,1.4569
2051,1.476
2052,1.4631
2053,1.4656
2054,1.464
2055,1.468
2056,1.4794
2057,1.4795
2058,1.473
2059,1.4764
2060,1.489
2061,1.4905
2062,1.4832
2063,1.4867
2064,1.4939
2065,1.5133
2066,1.5087
2067,1.5156
2068,1.5265
2069,1.5378
2070,1.5425
2071,1.5391
2072,1.5486
2073,1.5228
2074,1.5315
2075,1.5358
2076,1.5561
2077,1.5676
2078,1.5625
2079,1.5621
2080,1.5766
2081,1.5695
2082,1.5669
2083,1.5621
2084,1.5614
2085,1.5676
2086,1.5619
2087,1.561
2088,1.5506
2089,1.5746
2090,1.5784
2091,1.5778
2092,1.5727
2093,1.5754
2094,1.588
2095,1.5898
2096,1.5988
2097,1.5982
2098,1.5963
2099,1.6049
2100,1.5966
2101,1.6068
2102,1.6307
2103,1.6433
2104,1.6294
2105,1.6343
2106,1.6409
2107,1.6506
2108,1.6708
2109,1.675
2110,1.6662
2111,1.6623
2112,1.6483
2113,1.6537
2114,1.6565
2115,1.6657
2116,1.6689
2117,1.6736
2118,1.6719
2119,1.6793
2120,1.6701
2121,1.66
2122,1.6227
2123,1.5931
2124,1.6119
2125,1.6129
2126,1.6086
2127,1.6353
2128,1.6276
2129,1.6098
2130,1.6175
2131,1.6269
2132,1.6448
2133,1.6475
2134,1.6491
2135,1.6413
2136,1.612
2137,1.6199
2138,1.617
2139,1.6081
2140,1.595
2141,1.5733
2142,1.5715
2143,1.5967
2144,1.5898
2145,1.5904
2146,1.5779
2147,1.589
2148,1.5912
2149,1.5886
2150,1.581
2151,1.5872
2152,1.5931
2153,1.5926
2154,1.5916
2155,1.5862
2156,1.5901
2157,1.5848
2158,1.6044
2159,1.6053
2160,1.5864
2161,1.5759
2162,1.5718
2163,1.561
2164,1.5724
2165,1.5745
2166,1.5656
2167,1.5644
2168,1.5696
2169,1.5613
2170,1.5601
2171,1.5535
2172,1.5394
2173,1.5473
2174,1.539
2175,1.5295
2176,1.5257
2177,1.5327
2178,1.5422
2179,1.5435
2180,1.5515
2181,1.5516
2182,1.5715
2183,1.5753
2184,1.5732
2185,1.5865
2186,1.5909
2187,1.5757
2188,1.5669
2189,1.5824
2190,1.5875
2191,1.6009
2192,1.6164
2193,1.6255
2194,1.6221
2195,1.6308
2196,1.6303
2197,1.6229
2198,1.6161
2199,1.6272
2200,1.6062
2201,1.616
2202,1.6189
2203,1.62
2204,1.6302
2205,1.6249
2206,1.6194
2207,1.6157
2208,1.6096
2209,1.6107
2210,1.6162
2211,1.6038
2212,1.6057
2213,1.594
2214,1.6014
2215,1.6013
2216,1.6143
2217,1.6216
2218,1.6238
2219,1.6317
2220,1.6393
2221,1.6302
2222,1.6399
2223,1.652
2224,1.651
2225,1.6741
2226,1.631
2227,1.6275
2228,1.623
2229,1.6358
2230,1.67
2231,1.6733
2232,1.6982
2233,1.7115
2234,1.7033
2235,1.7125
2236,1.7218
2237,1.7286
2238,1.7506
2239,1.7673
2240,1.7756
2241,1.7723
2242,1.7636
2243,1.7491
2244,1.7476
2245,1.7221
2246,1.7417
2247,1.7433
2248,1.7548
2249,1.7686
2250,1.7739
2251,1.7574
2252,1.7773
2253,1.7764
2254,1.789
2255,1.8183
2256,1.8044
2257,1.8029
2258,1.792
2259,1.7848
2260,1.7839
2261,1.7852
2262,1.793
2263,1.815
2264,1.8247
2265,1.8321
2266,1.8204
2267,1.8107
2268,1.812
2269,1.8075
2270,1.8064
2271,1.8095
2272,1.8
2273,1.8125
2274,1.838
2275,1.8345
2276,1.8622
2277,1.8451
2278,1.8014
2279,1.7763
2280,1.7849
2281,1.777
2282,1.7924
2283,1.7899
2284,1.7934
2285,1.7888
2286,1.7432
2287,1.7411
2288,1.743
2289,1.7641
2290,1.7667
2291,1.7549
2292,1.7455
2293,1.7467
2294,1.7512
2295,1.7506
2296,1.7375
2297,1.7183
2298,1.7319
2299,1.7328
2300,1.7247
2301,1.7143
2302,1.7122
2303,1.7013
2304,1.7214
2305,1.7175
2306,1.6978
2307,1.7042
2308,1.708
2309,1.7119
2310,1.7116
2311,1.7089
2312,1.7245
2313,1.7261
2314,1.727
2315,1.7254
2316,1.7319
2317,1.7319
2318,1.7343
2319,1.728
2320,1.7291
2321,1.7327
2322,1.7827
2323,1.8082
2324,1.8133
2325,1.8081
2326,1.8193
2327,1.8155
2328,1.8271
2329,1.8158
2330,1.8087
2331,1.7927
2332,1.8033
2333,1.8016
2334,1.8098
2335,1.8124
2336,1.8051
2337,1.8242
2338,1.8411
2339,1.8353
2340,1.8612
2341,1.8578
2342,1.8567
2343,1.8447
2344,1.8538
2345,1.8346
2346,1.8319
2347,1.8236
2348,1.8542
2349,1.8693
2350,1.8847
2351,1.8814
2352,1.88
2353,1.8824
2354,1.8696
2355,1.8521
2356,1.8544
2357,1.8498
2358,1.8508
2359,1.8602
2360,1.8494
2361,1.843
2362,1.8454
2363,1.8434
2364,1.8618
2365,1.8663
2366,1.8692
2367,1.8671
2368,1.8742
2369,1.8786
2370,1.8491
2371,1.8489
2372,1.8577
2373,1.8538
2374,1.8597
2375,1.8622
2376,1.8569
2377,1.8536
2378,1.8501
2379,1.8329
2380,1.8132
2381,1.7807
2382,1.7789
2383,1.7802
2384,1.7928
2385,1.802
2386,1.7972
2387,1.7997
2388,1.8041
2389,1.7725
2390,1.7651
2391,1.7657
2392,1.7592
2393,1.7619
2394,1.762
2395,1.749
2396,1.7358
2397,1.7103
2398,1.6741
2399,1.691
2400,1.6842
2401,1.6754
2402,1.6687
2403,1.6493
2404,1.6737
2405,1.6848
2406,1.6875
2407,1.6694
2408,1.6587
2409,1.6619
2410,1.6602
2411,1.6617
2412,1.6302
2413,1.6367
2414,1.6566
2415,1.6724
2416,1.687
2417,1.7029
2418,1.7006
2419,1.6785
2420,1.6939
2421,1.6952
2422,1.679
2423,1.6792
2424,1.6809
2425,1.6754
2426,1.6778
2427,1.6626
2428,1.6641
2429,1.6544
2430,1.6551
2431,1.668
2432,1.685
2433,1.6803
2434,1.692
2435,1.6606
2436,1.6669
2437,1.6685
2438,1.6449
2439,1.648
2440,1.6439
2441,1.6586
2442,1.6492
2443,1.6472
2444,1.6367
2445,1.6299
2446,1.6257
2447,1.6368
2448,1.6554
2449,1.6541
2450,1.6466
2451,1.6479
2452,1.6489
2453,1.6464
2454,1.6257
2455,1.6256
2456,1.6244
2457,1.6248
2458,1.6381
2459,1.6261
2460,1.6201
2461,1.6228
2462,1.6187
2463,1.6344
2464,1.6416
2465,1.6418
2466,1.6452
2467,1.6545
2468,1.6529
2469,1.6509
2470,1.6524
2471,1.6572
2472,1.6694
2473,1.6779
2474,1.6883
2475,1.7059
2476,1.7124
2477,1.7103
2478,1.7054
2479,1.7095
2480,1.7205
2481,1.7177
2482,1.7047
2483,1.7079
2484,1.7135
2485,1.7215
2486,1.7219
2487,1.7217
2488,1.7155
2489,1.7251
2490,1.7277
2491,1.7179
2492,1.7258
2493,1.7221
2494,1.7427
2495,1.7491
2496,1.7691
2497,1.7625
2498,1.7591
2499,1.7736
2500,1.7699
2501,1.7706
2502,1.7736
2503,1.7827
2504,1.7901
2505,1.7916
2506,1.7949
2507,1.7817
2508,1.7925
2509,1.7898
2510,1.7956
2511,1.7998
2512,1.8115
2513,1.8109
2514,1.787
2515,1.7954
2516,1.7905
2517,1.7857
2518,1.7738
2519,1.7788
2520,1.779
2521,1.7623
2522,1.7719
2523,1.7588
2524,1.757
2525,1.7498
2526,1.751
2527,1.7365
2528,1.7413
2529,1.758
2530,1.7752
2531,1.7561
2532,1.7462
2533,1.7315
2534,1.7208
2535,1.7213
2536,1.7374
2537,1.7361
2538,1.7355
2539,1.7165
2540,1.7252
2541,1.7193
2542,1.7123
2543,1.7243
2544,1.7315
2545,1.7316
2546,1.7255
2547,1.729
2548,1.7219
2549,1.7179
2550,1.7149
2551,1.7094
2552,1.7109
2553,1.704
2554,1.6974
2555,1.7054
2556,1.7051
2557,1.7182
2558,1.7168
2559,1.7119
2560,1.7255
2561,1.7415
2562,1.7355
2563,1.7409
2564,1.7283
2565,1.7147
2566,1.7093
2567,1.7215
2568,1.7183
2569,1.7072
2570,1.7069
2571,1.6866
2572,1.6891
2573,1.6855
2574,1.6907
2575,1.6901
2576,1.6891
2577,1.6871
2578,1.6849
2579,1.6854
2580,1.6916
2581,1.6938
2582,1.6887
2583,1.686
2584,1.6851
2585,1.702
2586,1.701
2587,1.6996
2588,1.6711
2589,1.6641
2590,1.6614
2591,1.66
2592,1.6555
2593,1.6788
2594,1.6709
2595,1.6718
2596,1.6639
2597,1.6647
2598,1.6618
2599,1.6562
2600,1.6636
2601,1.6647
2602,1.678
2603,1.6817
2604,1.6721
2605,1.672
2606,1.6724
2607,1.6649
2608,1.6606
2609,1.6517
2610,1.6519
2611,1.6477
2612,1.6441
2613,1.6447
2614,1.6469
2615,1.6333
2616,1.634
2617,1.6183
2618,1.628
2619,1.625
2620,1.6262
2621,1.5909
2622,1.5935
2623,1.5669
2624,1.5696
2625,1.5723
2626,1.5296
2627,1.5235
2628,1.5127
2629,1.5251
2630,1.5409
2631,1.5001
2632,1.5093
2633,1.5124
2634,1.526
2635,1.5155
2636,1.503
2637,1.5128
2638,1.5062
2639,1.4835
2640,1.4544
2641,1.4454
2642,1.4454
2643,1.441
2644,1.4757
2645,1.4817
2646,1.488
2647,1.4808
2648,1.4946
2649,1.496
2650,1.4717
2651,1.4981
2652,1.4921
2653,1.4931
2654,1.4807
2655,1.5048
2656,1.5179
2657,1.5462
2658,1.5517
2659,1.5522
2660,1.5689
2661,1.5549
2662,1.5506
2663,1.5539
2664,1.546
2665,1.543
2666,1.554
2667,1.5512
2668,1.5508
2669,1.5538
2670,1.5505
2671,1.5539
2672,1.5761
2673,1.5903
2674,1.5752
2675,1.5874
2676,1.577
2677,1.5892
2678,1.5677
2679,1.5465
2680,1.538
2681,1.5563
2682,1.5497
2683,1.5576
2684,1.518
2685,1.5175
2686,1.5158
2687,1.518
2688,1.498
2689,1.5073
2690,1.5147
2691,1.518
2692,1.5098
2693,1.5063
2694,1.5077
2695,1.5186
2696,1.5265
2697,1.51
2698,1.4985
2699,1.4915
2700,1.474
2701,1.4853
2702,1.4798
2703,1.4859
2704,1.4785
2705,1.4825
2706,1.4867
2707,1.4955
2708,1.4724
2709,1.5021
2710,1.5026
2711,1.518
2712,1.5154
2713,1.5136
2714,1.5434
2715,1.5504
2716,1.542
2717,1.5355
2718,1.5443
2719,1.5438
2720,1.5338
2721,1.5259
2722,1.5425
2723,1.5237
2724,1.4943
2725,1.4803
2726,1.4615
2727,1.4694
2728,1.4771
2729,1.4958
2730,1.4958
2731,1.5042
2732,1.5123
2733,1.5027
2734,1.5094
2735,1.5176
2736,1.5257
2737,1.5212
2738,1.4893
2739,1.4955
2740,1.4947
2741,1.4956
2742,1.4805
2743,1.4866
2744,1.4935
2745,1.4994
2746,1.5011
2747,1.5046
2748,1.4969
2749,1.4988
2750,1.4987
2751,1.499
2752,1.4974
2753,1.4823
2754,1.4724
2755,1.477
2756,1.4764
2757,1.4759
2758,1.4753
2759,1.474
2760,1.4747
2761,1.4759
2762,1.4811
2763,1.4756
2764,1.4731
2765,1.4802
2766,1.4886
2767,1.4882
2768,1.4905
2769,1.5008
2770,1.5152
2771,1.5133
2772,1.5084
2773,1.5168
2774,1.5157
2775,1.5141
2776,1.5123
2777,1.5241
2778,1.5316
2779,1.5358
2780,1.5224
2781,1.5235
2782,1.5248
2783,1.5239
2784,1.5385
2785,1.5505
2786,1.5619
2787,1.5635
2788,1.5662
2789,1.5643
2790,1.5746
2791,1.5684
2792,1.5602
2793,1.5577
2794,1.5542
2795,1.5511
2796,1.5466
2797,1.5512
2798,1.5621
2799,1.5602
2800,1.5684
2801,1.588
2802,1.5944
2803,1.5888
2804,1.5907
2805,1.5879
2806,1.6025
2807,1.6094
2808,1.6064
2809,1.5946
2810,1.5964
2811,1.5995
2812,1.5943
2813,1.599
2814,1.5987
2815,1.596
2816,1.6046
2817,1.6068
2818,1.6168
2819,1.618
2820,1.6118
2821,1.5998
2822,1.5938
2823,1.5937
2824,1.573
2825,1.5584
2826,1.544
2827,1.5524
2828,1.5435
2829,1.5456
2830,1.5247
2831,1.5167
2832,1.5087
2833,1.5198
2834,1.5205
2835,1.5333
2836,1.5256
2837,1.5197
2838,1.5002
2839,1.507
2840,1.5131
2841,1.5224
2842,1.5323
2843,1.5371
2844,1.5391
2845,1.5532
2846,1.5377
2847,1.5422
2848,1.5509
2849,1.5503
2850,1.5455
2851,1.5454
2852,1.5392
2853,1.5471
2854,1.5473
2855,1.5336
2856,1.5402
2857,1.55
2858,1.5464
2859,1.5438
2860,1.5423
2861,1.5438
2862,1.5429
2863,1.543
2864,1.5409
2865,1.5457
2866,1.55
2867,1.5517
2868,1.5661
2869,1.5749
2870,1.5845
2871,1.5797
2872,1.5844
2873,1.5846
2874,1.584
2875,1.5839
2876,1.5985
2877,1.6
2878,1.6055
2879,1.6035
2880,1.6052
2881,1.6011
2882,1.5984
2883,1.6014
2884,1.6052
2885,1.5856
2886,1.5911
2887,1.5784
2888,1.5877
2889,1.5939
2890,1.5961
2891,1.5907
2892,1.5937
2893,1.6116
2894,1.6177
2895,1.6175
2896,1.6114
2897,1.6174
2898,1.625
2899,1.6284
2900,1.6342
2901,1.6382
2902,1.6417
2903,1.6466
2904,1.6519
2905,1.6467
2906,1.6517
2907,1.6658
2908,1.6775
2909,1.6926
2910,1.6895
2911,1.6925
2912,1.7128
2913,1.722
2914,1.7054
2915,1.6941
2916,1.7073
2917,1.707
2918,1.7131
2919,1.7271
2920,1.7156
2921,1.7156
2922,1.7229
2923,1.7241
2924,1.7081
2925,1.7119
2926,1.7354
2927,1.7422
2928,1.7556
2929,1.7483
2930,1.7385
2931,1.7517
2932,1.7678
2933,1.7711
2934,1.7617
2935,1.7662
2936,1.7647
2937,1.7791
2938,1.7825
2939,1.7975
2940,1.7902
2941,1.8086
2942,1.8124
2943,1.818
2944,1.8234
2945,1.8508
2946,1.8505
2947,1.8466
2948,1.8468
2949,1.8219
2950,1.7883
2951,1.7697
2952,1.7741
2953,1.7927
2954,1.801
2955,1.7877
2956,1.7591
2957,1.7464
2958,1.7653
2959,1.7649
2960,1.7934
2961,1.8042
2962,1.8169
2963,1.7835
2964,1.7701
2965,1.7536
2966,1.7855
2967,1.7896
2968,1.7691
2969,1.7686
2970,1.7724
2971,1.7893
2972,1.785
2973,1.7949
2974,1.8077
2975,1.8184
2976,1.888
2977,1.8871
2978,1.89
2979,1.8806
2980,1.8926
2981,1.8692
2982,1.8735
2983,1.8861
2984,1.8701
2985,1.8741
2986,1.8656
2987,1.8616
2988,1.8691
2989,1.8733
2990,1.8701
2991,1.8687
2992,1.8628
2993,1.8662
2994,1.8675
2995,1.8705
2996,1.8854
2997,1.8957
2998,1.8951
2999,1.881
3000,1.8867
3001,1.8854
3002,1.8838
3003,1.8786
3004,1.8762
3005,1.8851
3006,1.894
3007,1.8915
3008,1.8911
3009,1.894
3010,1.8901
3011,1.8878
3012,1.898
3013,1.8962
3014,1.8898
3015,1.8627
3016,1.8493
3017,1.85
3018,1.8463
3019,1.8577
3020,1.8685
3021,1.8668
3022,1.8575
3023,1.8586
3024,1.859
3025,1.8551
3026,1.8446
3027,1.847
3028,1.8427
3029,1.8309
3030,1.8025
3031,1.791
3032,1.8034
3033,1.8282
3034,1.8422
3035,1.8439
3036,1.8537
3037,1.8435
3038,1.8158
3039,1.8161
3040,1.83
3041,1.8142
3042,1.8127
3043,1.8142
3044,1.8132
3045,1.8099
3046,1.8268
3047,1.8413
3048,1.8582
3049,1.8483
3050,1.8518
3051,1.8698
3052,1.8646
3053,1.8711
3054,1.8783
3055,1.857
3056,1.8625
3057,1.8785
3058,1.8775
3059,1.8855
3060,1.8996
3061,1.8991
3062,1.8916
3063,1.8959
3064,1.8946
3065,1.8991
3066,1.892
3067,1.8793
3068,1.8713
3069,1.8685
3070,1.8618
3071,1.8738
3072,1.8674
3073,1.8421
3074,1.8311
3075,1.8362
3076,1.8349
3077,1.8252
3078,1.8204
3079,1.8268
3080,1.8071
3081,1.8123
3082,1.7961
3083,1.7809
3084,1.7821
3085,1.7769
3086,1.7791
3087,1.7588
3088,1.7178
3089,1.7061
3090,1.7119
3091,1.7222
3092,1.7241
3093,1.6918
3094,1.677
3095,1.6673
3096,1.6694
3097,1.6912
3098,1.7053
3099,1.7018
3100,1.7084
3101,1.6964
3102,1.7135
3103,1.7087
3104,1.7196
3105,1.706
3106,1.7196
3107,1.7137
3108,1.713
3109,1.7027
3110,1.6564
3111,1.6259
3112,1.6415
3113,1.6316
3114,1.6194
3115,1.6164
3116,1.6035
3117,1.6493
3118,1.6658
3119,1.6453
3120,1.6293
3121,1.6528
3122,1.6531
3123,1.6369
3124,1.6451
3125,1.6553
3126,1.6677
3127,1.6801
3128,1.6834
3129,1.6466
3130,1.6453
3131,1.6656
3132,1.6547
3133,1.6615
3134,1.6626
3135,1.6721
3136,1.6729
3137,1.6468
3138,1.6373
3139,1.6281
3140,1.6351
3141,1.6273
3142,1.6272
3143,1.6169
3144,1.6096
3145,1.6069
3146,1.5894
3147,1.5801
3148,1.5809
3149,1.5648
3150,1.5548
3151,1.5723
3152,1.5801
3153,1.5728
3154,1.5868
3155,1.5719
3156,1.5823
3157,1.5779
3158,1.5646
3159,1.5631
3160,1.5469
3161,1.552
3162,1.5502
3163,1.5594
3164,1.5721
3165,1.5706
3166,1.5649
3167,1.5525
3168,1.587
3169,1.589
3170,1.5889
3171,1.5938
3172,1.6089
3173,1.6254
3174,1.6244
3175,1.6217
3176,1.6337
3177,1.6159
3178,1.6259
3179,1.6145
3180,1.619
3181,1.6195
3182,1.6158
3183,1.6239
3184,1.6416
3185,1.6468
3186,1.6388
3187,1.6328
3188,1.6278
3189,1.6254
3190,1.6233
3191,1.6191
3192,1.6174
3193,1.5951
3194,1.5606
3195,1.5723
3196,1.603
3197,1.6219
3198,1.6067
3199,1.6112
3200,1.6199
3201,1.6176
3202,1.6086
3203,1.617
3204,1.6265
3205,1.6293
3206,1.6304
3207,1.6296
3208,1.6636
3209,1.6641
3210,1.6605
3211,1.6714
3212,1.6711
3213,1.6752
3214,1.6742
3215,1.6649
3216,1.6636
3217,1.6618
3218,1.6776
3219,1.6763
3220,1.6667
3221,1.669
3222,1.6678
3223,1.6813
3224,1.6781
3225,1.6827
3226,1.6802
3227,1.6702
3228,1.6639
3229,1.6512
3230,1.6394
3231,1.647
3232,1.6488
3233,1.6469
3234,1.6316
3235,1.6356
3236,1.6402
3237,1.6493
3238,1.6491
3239,1.6414
3240,1.6358
3241,1.6386
3242,1.6378
3243,1.6321
3244,1.6456
3245,1.6601
3246,1.6606
3247,1.6682
3248,1.6972
3249,1.6885
3250,1.6921
3251,1.6963
3252,1.6909
3253,1.6901
3254,1.6949
3255,1.6934
3256,1.6989
3257,1.6867
3258,1.7109
3259,1.7094
3260,1.7083
3261,1.7094
3262,1.7066
3263,1.7054
3264,1.7005
3265,1.6795
3266,1.6782
3267,1.6741
3268,1.6864
3269,1.6818
3270,1.678
3271,1.6959
3272,1.7139
3273,1.7131
3274,1.7125
3275,1.7097
3276,1.7093
3277,1.7206
3278,1.7279
3279,1.7254
3280,1.7291
3281,1.7338
3282,1.7518
3283,1.7648
3284,1.7662
3285,1.7672
3286,1.7596
3287,1.7548
3288,1.7629
3289,1.7452
3290,1.7652
3291,1.7684
3292,1.7633
3293,1.7391
3294,1.7032
3295,1.6973
3296,1.7081
3297,1.6592
3298,1.6654
3299,1.6923
3300,1.7024
3301,1.7137
3302,1.7148
3303,1.7039
3304,1.7119
3305,1.6868
3306,1.705
3307,1.712
3308,1.691
3309,1.6997
3310,1.7032
3311,1.7088
3312,1.7173
3313,1.7218
3314,1.7362
3315,1.7296
3316,1.7115
3317,1.6927
3318,1.6805
3319,1.68
3320,1.6858
3321,1.6638
3322,1.6703
3323,1.6628
3324,1.6629
3325,1.6627
3326,1.6778
3327,1.6625
3328,1.6724
3329,1.672
3330,1.665
3331,1.657
3332,1.6422
3333,1.634
3334,1.633
3335,1.6403
3336,1.6366
3337,1.64
3338,1.6193
3339,1.6245
3340,1.6301
3341,1.6481
3342,1.6403
3343,1.6233
3344,1.6114
3345,1.6305
3346,1.6294
3347,1.6367
3348,1.6341
3349,1.6467
3350,1.6387
3351,1.6419
3352,1.6259
3353,1.6325
3354,1.6426
3355,1.6506
3356,1.6462
3357,1.6512
3358,1.6517
3359,1.6811
3360,1.6721
3361,1.6786
3362,1.6725
3363,1.6595
3364,1.6635
3365,1.6723
3366,1.676
3367,1.6799
3368,1.689
3369,1.6849
3370,1.6831
3371,1.6831
3372,1.6944
3373,1.6932
3374,1.7007
3375,1.7053
3376,1.6987
3377,1.7045
3378,1.7177
3379,1.7228
3380,1.7291
3381,1.7333
3382,1.746
3383,1.748
3384,1.7394
3385,1.731
3386,1.729
3387,1.7386
3388,1.7164
3389,1.7185
3390,1.7436
3391,1.7369
3392,1.7396
3393,1.7289
3394,1.7359
3395,1.7436
3396,1.7446
3397,1.7434
3398,1.7457
3399,1.758
3400,1.7602
3401,1.7662
3402,1.7645
3403,1.7666
3404,1.7737
3405,1.7703
3406,1.7698
3407,1.7703
3408,1.7836
3409,1.7962
3410,1.7999
3411,1.8076
3412,1.8038
3413,1.813
3414,1.8159
3415,1.8054
3416,1.8074
3417,1.8172
3418,1.816
3419,1.8022
3420,1.8141
3421,1.8182
3422,1.8066
3423,1.8162
3424,1.8247
3425,1.8351
3426,1.8025
3427,1.7955
3428,1.7912
3429,1.7996
3430,1.7864
3431,1.8065
3432,1.8134
3433,1.8057
3434,1.8039
3435,1.8114
3436,1.812
3437,1.8079
3438,1.8005
3439,1.7927
3440,1.8107
3441,1.8107
3442,1.8039
3443,1.8092
3444,1.8138
3445,1.8027
3446,1.8091
3447,1.8121
3448,1.8136
3449,1.8181
3450,1.8122
3451,1.8682
3452,1.8645
3453,1.8561
3454,1.8527
3455,1.8575
3456,1.8717
3457,1.8758
3458,1.8592
3459,1.8655
3460,1.8703
3461,1.8756
3462,1.8436
3463,1.848
3464,1.8039
3465,1.7737
3466,1.7611
3467,1.6917
3468,1.6825
3469,1.657
3470,1.6298
3471,1.6305
3472,1.6325
3473,1.6299
3474,1.6304
3475,1.6474
3476,1.688
3477,1.6936
3478,1.6675
3479,1.6372
3480,1.6323
3481,1.633
3482,1.6405
3483,1.6145
3484,1.6239
3485,1.6302
3486,1.6441
3487,1.6353
3488,1.6297
3489,1.6028
3490,1.5762
3491,1.5704
3492,1.5685
3493,1.5812
3494,1.57
3495,1.5495
3496,1.5355
3497,1.5394
3498,1.531
3499,1.521
3500,1.497
3501,1.5112
3502,1.512
3503,1.5032
3504,1.5065
3505,1.498
3506,1.4846
3507,1.4924
3508,1.4871
3509,1.5087
3510,1.4857
3511,1.4804
3512,1.4882
3513,1.4976
3514,1.4852
3515,1.4802
3516,1.4809
3517,1.4925
3518,1.4876
3519,1.4746
3520,1.4789
3521,1.4905
3522,1.5128
3523,1.5286
3524,1.5241
3525,1.5431
3526,1.5545
3527,1.5255
3528,1.5218
3529,1.5215
3530,1.5275
3531,1.5292
3532,1.5386
3533,1.5355
3534,1.5285
3535,1.5239
3536,1.499
3537,1.4927
3538,1.494
3539,1.4664
3540,1.4764
3541,1.4784
3542,1.4629
3543,1.4929
3544,1.5007
3545,1.5021
3546,1.5006
3547,1.5148
3548,1.5029
3549,1.5027
3550,1.4949
3551,1.4956
3552,1.5088
3553,1.5085
3554,1.5001
3555,1.481
3556,1.4866
3557,1.5195
3558,1.506
3559,1.4837
3560,1.4783
3561,1.4572
3562,1.4275
3563,1.4162
3564,1.4121
3565,1.4176
3566,1.424
3567,1.411
3568,1.4065
3569,1.4026
3570,1.3919
3571,1.3944
3572,1.3925
3573,1.4201
3574,1.4148
3575,1.412
3576,1.4266
3577,1.428
3578,1.4276
3579,1.4049
3580,1.4025
3581,1.3932
3582,1.413
3583,1.4212
3584,1.4213
3585,1.4236
3586,1.4217
3587,1.4191
3588,1.4087
3589,1.4071
3590,1.4084
3591,1.4079
3592,1.4073
3593,1.4196
3594,1.4202
3595,1.4428
3596,1.4622
3597,1.4557
3598,1.4502
3599,1.4514
3600,1.4409
3601,1.4589
3602,1.4579
3603,1.4654
3604,1.4745
3605,1.4913
3606,1.4884
3607,1.4894
3608,1.4793
3609,1.4814
3610,1.4934
3611,1.5249
3612,1.5167
3613,1.5138
3614,1.4879
3615,1.5
3616,1.5043
3617,1.4988
3618,1.5067
3619,1.5342
3620,1.5496
3621,1.5404
3622,1.53
3623,1.5331
3624,1.5257
3625,1.5305
3626,1.521
3627,1.5291
3628,1.5368
3629,1.5007
3630,1.5056
3631,1.5015
3632,1.4873
3633,1.4995
3634,1.4981
3635,1.4939
3636,1.5032
3637,1.5155
3638,1.5039
3639,1.5034
3640,1.5106
3641,1.5118
3642,1.519
3643,1.5297
3644,1.5256
3645,1.5103
3646,1.5098
3647,1.4951
3648,1.4913
3649,1.49
3650,1.4811
3651,1.4884
3652,1.4934
3653,1.4946
3654,1.4884
3655,1.4722
3656,1.4815
3657,1.4657
3658,1.4607
3659,1.454
3660,1.4463
3661,1.4399
3662,1.4512
3663,1.464
3664,1.4786
3665,1.4701
3666,1.4762
3667,1.4788
3668,1.4805
3669,1.48
3670,1.4683
3671,1.461
3672,1.4488
3673,1.4457
3674,1.4607
3675,1.4697
3676,1.4585
3677,1.4465
3678,1.468
3679,1.4696
3680,1.4842
3681,1.4801
3682,1.4675
3683,1.472
3684,1.4618
3685,1.4659
3686,1.4595
3687,1.4555
3688,1.4563
3689,1.4784
3690,1.4747
3691,1.4673
3692,1.4648
3693,1.4693
3694,1.4543
3695,1.4517
3696,1.4239
3697,1.4317
3698,1.4537
3699,1.4672
3700,1.4835
3701,1.4769
3702,1.4814
3703,1.4761
3704,1.4691
3705,1.4509
3706,1.4666
3707,1.4695
3708,1.4655
3709,1.4771
3710,1.4684
3711,1.4975
3712,1.4976
3713,1.5086
3714,1.5082
3715,1.5206
3716,1.5161
3717,1.5131
3718,1.5121
3719,1.5216
3720,1.4993
3721,1.502
3722,1.4996
3723,1.497
3724,1.4874
3725,1.4731
3726,1.4723
3727,1.48
3728,1.4747
3729,1.4806
3730,1.4672
3731,1.467
3732,1.4849
3733,1.4835
3734,1.4928
3735,1.4906
3736,1.5041
3737,1.5001
3738,1.5047
3739,1.4931
3740,1.4874
3741,1.483
3742,1.4712
3743,1.4599
3744,1.461
3745,1.4604
3746,1.4524
3747,1.461
3748,1.4533
3749,1.4526
3750,1.4535
3751,1.4629
3752,1.4519
3753,1.4563
3754,1.4571
3755,1.456
3756,1.4558
3757,1.4586
3758,1.4415
3759,1.4503
3760,1.4546
3761,1.4533
3762,1.4695
3763,1.4648
3764,1.4553
3765,1.4558
3766,1.4511
3767,1.4542
3768,1.4594
3769,1.4683
3770,1.4667
3771,1.4535
3772,1.4652
3773,1.4605
3774,1.4636
3775,1.4598
3776,1.4729
3777,1.4816
3778,1.4769
3779,1.4803
3780,1.4763
3781,1.4761
3782,1.4738
3783,1.4712
3784,1.4656
3785,1.4677
3786,1.4658
3787,1.4653
3788,1.4698
3789,1.4726
3790,1.4832
3791,1.4822
3792,1.4725
3793,1.4583
3794,1.459
3795,1.4636
3796,1.4673
3797,1.4686
3798,1.4726
3799,1.4739
3800,1.4628
3801,1.4771
3802,1.4725
3803,1.4687
3804,1.47
3805,1.4769
3806,1.4708
3807,1.4792
3808,1.4724
3809,1.4739
3810,1.4716
3811,1.4703
3812,1.4706
3813,1.4819
3814,1.4775
3815,1.4865
3816,1.4754
3817,1.4773
3818,1.4719
3819,1.4623
3820,1.4544
3821,1.4449
3822,1.4457
3823,1.4513
3824,1.4539
3825,1.4598
3826,1.4636
3827,1.4608
3828,1.4635
3829,1.4627
3830,1.4649
3831,1.4624
3832,1.4669
3833,1.4767
3834,1.4733
3835,1.473
3836,1.4835
3837,1.484
3838,1.48
3839,1.4805
3840,1.4779
3841,1.4827
3842,1.4926
3843,1.4927
3844,1.4843
3845,1.4817
3846,1.4816
3847,1.486
3848,1.4784
3849,1.4744
3850,1.4771
3851,1.4827
3852,1.482
3853,1.4831
3854,1.4831
3855,1.4783
3856,1.4654
3857,1.4707
3858,1.4527
3859,1.4569
3860,1.4566
3861,1.4634
3862,1.4638
3863,1.4661
3864,1.4653
3865,1.468
3866,1.4658
3867,1.4639
3868,1.4735
3869,1.4796
3870,1.4892
3871,1.4775
3872,1.4833
3873,1.4938
3874,1.4983
3875,1.4999
3876,1.5099
3877,1.5027
3878,1.4917
3879,1.4911
3880,1.4892
3881,1.4941
3882,1.4887
3883,1.4876
3884,1.4987
3885,1.4997
3886,1.5033
3887,1.5019
3888,1.5022
3889,1.5041
3890,1.5053
3891,1.502
3892,1.5039
3893,1.5073
3894,1.5042
3895,1.5038
3896,1.5055
3897,1.5101
3898,1.5045
3899,1.4977
3900,1.5
3901,1.498
3902,1.4987
3903,1.4995
3904,1.5002
3905,1.5114
3906,1.509
3907,1.5125
3908,1.5123
3909,1.5111
3910,1.5306
3911,1.5297
3912,1.5272
3913,1.5313
3914,1.5373
3915,1.5483
3916,1.5413
3917,1.542
3918,1.5377
3919,1.5334
3920,1.5341
3921,1.5353
3922,1.5442
3923,1.5344
3924,1.5347
3925,1.56
3926,1.5678
3927,1.5628
3928,1.56
3929,1.5558
3930,1.5595
3931,1.5531
3932,1.5436
3933,1.5339
3934,1.5247
3935,1.5289
3936,1.5211
3937,1.5239
3938,1.5245
3939,1.5198
3940,1.5244
3941,1.5252
3942,1.5268
3943,1.5232
3944,1.5293
3945,1.5302
3946,1.5283
3947,1.5291
3948,1.5206
3949,1.5318
3950,1.5278
3951,1.5265
3952,1.5251
3953,1.5324
3954,1.5352
3955,1.5383
3956,1.5396
3957,1.5421
3958,1.5383
3959,1.5271
3960,1.5185
3961,1.5232
3962,1.5257
3963,1.5317
3964,1.5337
3965,1.5358
3966,1.5318
3967,1.5333
3968,1.5402
3969,1.5467
3970,1.5454
3971,1.5517
3972,1.5452
3973,1.5658
3974,1.5491
3975,1.5557
3976,1.5591
3977,1.5588
3978,1.5616
3979,1.5562
3980,1.5594
3981,1.5614
3982,1.5644
3983,1.5614
3984,1.5617
3985,1.5622
3986,1.5722
3987,1.5747
3988,1.578
3989,1.5716
3990,1.569
3991,1.5702
3992,1.5717
3993,1.5822
3994,1.5967
3995,1.6025
3996,1.6066
3997,1.608
3998,1.6159
3999,1.6172
4000,1.6254
4001,1.6198
4002,1.6254
4003,1.6125
4004,1.6182
4005,1.6208
4006,1.6326
4007,1.6124
4008,1.6006
4009,1.6043
4010,1.6097
4011,1.5952
4012,1.5879
4013,1.5911
4014,1.5762
4015,1.5749
4016,1.5665
4017,1.5709
4018,1.566
4019,1.5647
4020,1.5672
4021,1.5671
4022,1.5583
4023,1.5586
4024,1.5603
4025,1.5674
4026,1.5647
4027,1.5662
4028,1.5596
4029,1.5577
4030,1.5608
4031,1.5609
4032,1.562
4033,1.5587
4034,1.563
4035,1.5613
4036,1.5612
4037,1.56
4038,1.5612
4039,1.5598
4040,1.5582
4041,1.558
4042,1.5439
4043,1.5455
4044,1.5435
4045,1.5581
4046,1.5627
4047,1.5615
4048,1.5605
4049,1.5618
4050,1.5524
4051,1.5532
4052,1.5577
4053,1.5595
4054,1.5684
4055,1.5661
4056,1.5651
4057,1.5618
4058,1.5683
4059,1.5658
4060,1.5858
4061,1.59
4062,1.5913
4063,1.5855
4064,1.5871
4065,1.5846
4066,1.5827
4067,1.5801
4068,1.5746
4069,1.5771
4070,1.5562
4071,1.5517
4072,1.5492
4073,1.5446
4074,1.5473
4075,1.5526
4076,1.5548
4077,1.547
4078,1.5532
4079,1.5663
4080,1.5659
4081,1.5726
4082,1.5687
4083,1.577
4084,1.5779
4085,1.5664
4086,1.5682
4087,1.5666
4088,1.5652
4089,1.5762
4090,1.6133
4091,1.63
4092,1.613
4093,1.6078
4094,1.6042
4095,1.5684
4096,1.5759
4097,1.573
4098,1.5862
4099,1.579
4100,1.5709
4101,1.5693
4102,1.5675
4103,1.575
4104,1.5825
4105,1.5823
4106,1.5836
4107,1.5876
4108,1.6007
4109,1.5853
4110,1.6176
4111,1.6062
4112,1.5924
4113,1.5924
4114,1.5975
4115,1.5953
4116,1.582
4117,1.5847
4118,1.5768
4119,1.5929
4120,1.6057
4121,1.6035
4122,1.5968
4123,1.5934
4124,1.5925
4125,1.5973
4126,1.594
4127,1.6015
4128,1.5935
4129,1.5989
4130,1.5957
4131,1.5987
4132,1.6
4133,1.585
4134,1.5693
4135,1.5603
4136,1.551
4137,1.5537
4138,1.5409
4139,1.5501
4140,1.5509
4141,1.5472
4142,1.5577
4143,1.5519
4144,1.5545
4145,1.5585
4146,1.5861
4147,1.5891
4148,1.5837
4149,1.5731
4150,1.5747
4151,1.5686
4152,1.5763
4153,1.57
4154,1.5738
4155,1.5712
4156,1.58
4157,1.58
4158,1.5766
4159,1.5908
4160,1.5752
4161,1.5885
4162,1.5794
4163,1.5844
4164,1.5843
4165,1.5871
4166,1.5828
4167,1.5603
4168,1.5588
4169,1.5568
4170,1.5665
4171,1.5678
4172,1.5759
4173,1.5724
4174,1.5724
4175,1.5776
4176,1.5707
4177,1.5668
4178,1.5673
4179,1.5706
4180,1.5782
4181,1.5746
4182,1.5735
4183,1.575
4184,1.5764
4185,1.5802
4186,1.5746
4187,1.58
4188,1.5703
4189,1.5792
4190,1.5783
4191,1.5842
4192,1.5831
4193,1.5807
4194,1.5828
4195,1.5878
4196,1.591
4197,1.5855
4198,1.5851
4199,1.5829
4200,1.5726
4201,1.5618
4202,1.5598
4203,1.536
4204,1.5368
4205,1.525
4206,1.5315
4207,1.5274
4208,1.5242
4209,1.5307
4210,1.529
4211,1.5292
4212,1.5325
4213,1.5306
4214,1.5351
4215,1.5399
4216,1.5396
4217,1.5433
4218,1.5354
4219,1.5394
4220,1.5356
4221,1.5366
4222,1.5423
4223,1.5383
4224,1.5361
4225,1.5402
4226,1.5318
4227,1.5326
4228,1.5386
4229,1.5534
4230,1.5666
4231,1.5582
4232,1.5553
4233,1.5581
4234,1.5697
4235,1.5712
4236,1.5774
4237,1.5694
4238,1.5706
4239,1.571
4240,1.5689
4241,1.5711
4242,1.5634
4243,1.5594
4244,1.5565
4245,1.5572
4246,1.5604
4247,1.5579
4248,1.5552
4249,1.5575
4250,1.5616
4251,1.5664
4252,1.5674
4253,1.5651
4254,1.5595
4255,1.5663
4256,1.5629
4257,1.5674
4258,1.5638
4259,1.5656
4260,1.5653
4261,1.5655
4262,1.5645
4263,1.5665
4264,1.5644
4265,1.5614
4266,1.5445
4267,1.5505
4268,1.5433
4269,1.5425
4270,1.5381
4271,1.5325
4272,1.5456
4273,1.5489
4274,1.5509
4275,1.5485
4276,1.5399
4277,1.5355
4278,1.5237
4279,1.5179
4280,1.5199
4281,1.522
4282,1.5289
4283,1.5293
4284,1.5266
4285,1.5167
4286,1.5231
4287,1.5206
4288,1.5222
4289,1.5292
4290,1.529
4291,1.5278
4292,1.5328
4293,1.5259
4294,1.5268
4295,1.5296
4296,1.5477
4297,1.5441
4298,1.5375
4299,1.5427
4300,1.536
4301,1.5346
4302,1.5385
4303,1.5346
4304,1.5307
4305,1.5303
4306,1.5309
4307,1.5324
4308,1.5315
4309,1.5243
4310,1.515
4311,1.5106
4312,1.4978
4313,1.5022
4314,1.502
4315,1.5005
4316,1.5024
4317,1.4902
4318,1.4943
4319,1.4907
4320,1.497
4321,1.498
4322,1.5038
4323,1.5169
4324,1.5251
4325,1.5237
4326,1.5222
4327,1.5164
4328,1.5155
4329,1.518
4330,1.5225
4331,1.5218
4332,1.5337
4333,1.5318
4334,1.5265
4335,1.5298
4336,1.5281
4337,1.525
4338,1.5243
4339,1.5242
4340,1.5207
4341,1.5186
4342,1.5161
4343,1.5161
4344,1.5166
4345,1.5182
4346,1.519
4347,1.5155
4348,1.5138
4349,1.5099
4350,1.5144
4351,1.5151
4352,1.5146
4353,1.5224
4354,1.5239
4355,1.5271
4356,1.528
4357,1.5251
4358,1.5137
4359,1.5116
4360,1.5087
4361,1.5137
4362,1.5162
4363,1.5161
4364,1.5148
4365,1.5166
4366,1.5184
4367,1.5174
4368,1.5098
4369,1.5068
4370,1.5038
4371,1.5001
4372,1.501
4373,1.4997
4374,1.5
4375,1.5089
4376,1.5024
4377,1.5061
4378,1.5043
4379,1.505
4380,1.5036
4381,1.5022
4382,1.4941
4383,1.4903
4384,1.4942
4385,1.4969
4386,1.5056
4387,1.511
4388,1.518
4389,1.515
4390,1.5083
4391,1.5092
4392,1.5053
4393,1.5049
4394,1.5089
4395,1.5051
4396,1.5064
4397,1.5029
4398,1.506
4399,1.5055
4400,1.5052
4401,1.5119
4402,1.5282
4403,1.5445
4404,1.5446
4405,1.5454
4406,1.544
4407,1.5387
4408,1.5393
4409,1.5325
4410,1.5362
4411,1.5355
4412,1.5312
4413,1.5425
4414,1.5454
4415,1.5434
4416,1.545
4417,1.5431
4418,1.5421
4419,1.5418
4420,1.5422
4421,1.544
4422,1.5465
4423,1.5532
4424,1.5559
4425,1.5576
4426,1.5603
4427,1.5616
4428,1.5591
4429,1.5587
4430,1.5563
4431,1.5579
4432,1.5599
4433,1.555
4434,1.5543
4435,1.5606
4436,1.5511
4437,1.5474
4438,1.5487
4439,1.5517
4440,1.5531
4441,1.5554
4442,1.5595
4443,1.5578
4444,1.5612
4445,1.5587
4446,1.5571
4447,1.5571
4448,1.5412
4449,1.5425
4450,1.5355
4451,1.5399
4452,1.5471
4453,1.5459
4454,1.5484
4455,1.5485
4456,1.5477
4457,1.548
4458,1.5462
4459,1.5435
4460,1.5452
4461,1.5492
4462,1.548
4463,1.5534
4464,1.5571
4465,1.5607
4466,1.5595
4467,1.566
4468,1.5631
4469,1.5725
4470,1.57
4471,1.5715
4472,1.5662
4473,1.5625
4474,1.5589
4475,1.5572
4476,1.5569
4477,1.5543
4478,1.5571
4479,1.5561
4480,1.561
4481,1.551
4482,1.5552
4483,1.5565
4484,1.5572
4485,1.561
4486,1.5589
4487,1.5604
4488,1.5611
4489,1.5608
4490,1.5642
4491,1.5621
4492,1.5583
4493,1.559
4494,1.5582
4495,1.5596
4496,1.56
4497,1.5692
4498,1.5725
4499,1.5762
4500,1.5774
4501,1.5781
4502,1.5824
4503,1.5812
4504,1.589
4505,1.5881
4506,1.583
4507,1.5954
4508,1.6033
4509,1.601
4510,1.6188
4511,1.6149
4512,1.6222
4513,1.6311
4514,1.631
4515,1.6248
4516,1.6298
4517,1.6284
4518,1.6288
4519,1.6295
4520,1.6354
4521,1.6442
4522,1.6465
4523,1.6523
4524,1.6559
4525,1.6571
4526,1.6692
4527,1.6617
4528,1.6545
4529,1.6549
4530,1.6546
4531,1.6608
4532,1.6613
4533,1.6657
4534,1.6326
4535,1.6184
4536,1.6095
4537,1.6248
4538,1.6302
4539,1.6347
4540,1.6394
4541,1.6418
4542,1.6418
4543,1.6453
4544,1.6563
4545,1.6547
4546,1.6452
4547,1.6484
4548,1.6559
4549,1.656
4550,1.6734
4551,1.6724
4552,1.6934
4553,1.6734
4554,1.6741
4555,1.6664
4556,1.6781
4557,1.6711
4558,1.6769
4559,1.6669
4560,1.6559
4561,1.6545
4562,1.6641
4563,1.6621
4564,1.6558
4565,1.6509
4566,1.6493
4567,1.6427
4568,1.6161
4569,1.6169
4570,1.611
4571,1.5974
4572,1.6076
4573,1.6024
4574,1.5906
4575,1.6003
4576,1.6076
4577,1.6191
4578,1.6193
4579,1.6111
4580,1.6204
4581,1.6298
4582,1.6203
4583,1.6092
4584,1.6077
4585,1.6028
4586,1.5888
4587,1.5997
4588,1.599
4589,1.6069
4590,1.6213
4591,1.6221
4592,1.6228
4593,1.6173
4594,1.6187
4595,1.6095
4596,1.6076
4597,1.6007
4598,1.6025
4599,1.5967
4600,1.5932
4601,1.5976
4602,1.5847
4603,1.5891
4604,1.5931
4605,1.5778
4606,1.5789
4607,1.5854
4608,1.5826
4609,1.5936
4610,1.602
4611,1.6074
4612,1.618
4613,1.6207
4614,1.6373
4615,1.6352
4616,1.6318
4617,1.6307
4618,1.6195
4619,1.614
4620,1.6141
4621,1.6155
4622,1.6176
4623,1.6152
4624,1.6178
4625,1.6152
4626,1.6214
4627,1.6226
4628,1.6257
4629,1.6282
4630,1.6145
4631,1.6177
4632,1.6142
4633,1.6154
4634,1.621
4635,1.613
4636,1.6138
4637,1.6079
4638,1.6274
4639,1.6268
4640,1.612
4641,1.6098
4642,1.6158
4643,1.6223
4644,1.6317
4645,1.6308
4646,1.6284
4647,1.6294
4648,1.6362
4649,1.6362
4650,1.6229
4651,1.619
4652,1.6179
4653,1.6266
4654,1.6286
4655,1.6259
4656,1.6211
4657,1.6245
4658,1.6164
4659,1.6188
4660,1.6165
4661,1.6203
4662,1.6257
4663,1.6234
4664,1.6207
4665,1.6203
4666,1.624
4667,1.6235
4668,1.624
4669,1.6299
4670,1.6372
4671,1.6465
4672,1.6479
4673,1.6466
4674,1.6483
4675,1.6446
4676,1.6456
4677,1.6403
4678,1.6338
4679,1.663
4680,1.667
4681,1.6629
4682,1.6673
4683,1.6628
4684,1.6648
4685,1.6724
4686,1.6659
4687,1.6525
4688,1.654
4689,1.6498
4690,1.6517
4691,1.6556
4692,1.6544
4693,1.6579
4694,1.6505
4695,1.6428
4696,1.6116
4697,1.608
4698,1.609
4699,1.6136
4700,1.6133
4701,1.6071
4702,1.6036
4703,1.58
4704,1.5654
4705,1.559
4706,1.5706
4707,1.558
4708,1.5597
4709,1.5661
4710,1.5879
4711,1.5878
4712,1.5829
4713,1.5698
4714,1.565
4715,1.5835
4716,1.59
4717,1.5882
4718,1.5917
4719,1.5988
4720,1.5901
4721,1.5719
4722,1.562
4723,1.5648
4724,1.5647
4725,1.5616
4726,1.5687
4727,1.5659
4728,1.5677
4729,1.5877
4730,1.5842
4731,1.5738
4732,1.5807
4733,1.5934
4734,1.5859
4735,1.58
4736,1.5897
4737,1.5893
4738,1.6038
4739,1.5823
4740,1.5938
4741,1.5924
4742,1.5892
4743,1.5924
4744,1.5875
4745,1.5896
4746,1.5986
4747,1.598
4748,1.6027
4749,1.5974
4750,1.6009
4751,1.5958
4752,1.6011
4753,1.5988
4754,1.5947
4755,1.6094
4756,1.6138
4757,1.6137
4758,1.6078
4759,1.6113
4760,1.6324
4761,1.655
4762,1.6418
4763,1.6418
4764,1.6523
4765,1.6525
4766,1.6605
4767,1.6504
4768,1.6636
4769,1.6665
4770,1.6594
4771,1.6742
4772,1.6761
4773,1.6682
4774,1.6653
4775,1.6638
4776,1.6649
4777,1.6604
4778,1.6671
4779,1.6612
4780,1.664
4781,1.6537
4782,1.6434
4783,1.6463
4784,1.656
4785,1.6564
4786,1.6539
4787,1.6548
4788,1.648
4789,1.6293
4790,1.6212
4791,1.6205
4792,1.6255
4793,1.6272
4794,1.6264
4795,1.6067
4796,1.6081
4797,1.6197
4798,1.6347
4799,1.6429
4800,1.6369
4801,1.6456
4802,1.6444
4803,1.6492
4804,1.631
4805,1.6195
4806,1.6144
4807,1.6117
4808,1.6065
4809,1.5975
4810,1.5887
4811,1.5879
4812,1.5919
4813,1.6059
4814,1.6031
4815,1.6001
4816,1.6076
4817,1.6067
4818,1.5987
4819,1.5983
4820,1.6193
4821,1.6387
4822,1.6311
4823,1.6216
4824,1.6156
4825,1.6115
4826,1.6083
4827,1.609
4828,1.6153
4829,1.6255
4830,1.6282
4831,1.6238
4832,1.6076
4833,1.599
4834,1.6062
4835,1.6116
4836,1.6097
4837,1.6105
4838,1.6048
4839,1.6127
4840,1.6075
4841,1.6089
4842,1.6164
4843,1.6213
4844,1.6209
4845,1.6197
4846,1.619
4847,1.6214
4848,1.6263
4849,1.6207
4850,1.6175
4851,1.612
4852,1.612
4853,1.6141
4854,1.6182
4855,1.6306
4856,1.6435
4857,1.6384
4858,1.6435
4859,1.6441
4860,1.6407
4861,1.6382
4862,1.6504
4863,1.6487
4864,1.6496
4865,1.6591
4866,1.6559
4867,1.6516
4868,1.6489
4869,1.6488
4870,1.6433
4871,1.6328
4872,1.6342
4873,1.6415
4874,1.6418
4875,1.6483
4876,1.6601
4877,1.6603
4878,1.6671
4879,1.6597
4880,1.6527
4881,1.6503
4882,1.6505
4883,1.6418
4884,1.6449
4885,1.6479
4886,1.6469
4887,1.6491
4888,1.6503
4889,1.6432
4890,1.6367
4891,1.6391
4892,1.623
4893,1.6139
4894,1.6078
4895,1.6119
4896,1.6105
4897,1.6071
4898,1.6056
4899,1.5974
4900,1.6001
4901,1.6068
4902,1.6084
4903,1.6099
4904,1.6125
4905,1.6067
4906,1.6047
4907,1.6081
4908,1.6137
4909,1.6139
4910,1.6143
4911,1.6157
4912,1.6088
4913,1.6055
4914,1.6087
4915,1.6007
4916,1.6025
4917,1.6029
4918,1.606
4919,1.6212
4920,1.6264
4921,1.6411
4922,1.6419
4923,1.6393
4924,1.6325
4925,1.6345
4926,1.6364
4927,1.6303
4928,1.6323
4929,1.6347
4930,1.6264
4931,1.6249
4932,1.6144
4933,1.6142
4934,1.607
4935,1.6045
4936,1.5992
4937,1.6012
4938,1.6112
4939,1.6079
4940,1.6012
4941,1.607
4942,1.6097
4943,1.6178
4944,1.6157
4945,1.6089
4946,1.6112
4947,1.6267
4948,1.6243
4949,1.6213
4950,1.6132
4951,1.6107
4952,1.606
4953,1.5964
4954,1.6045
4955,1.6073
4956,1.6048
4957,1.6051
4958,1.6044
4959,1.6041
4960,1.6018
4961,1.5982
4962,1.5946
4963,1.5882
4964,1.5887
4965,1.593
4966,1.5982
4967,1.6046
4968,1.6115
4969,1.6109
4970,1.6077
4971,1.6184
4972,1.6367
4973,1.6507
4974,1.6417
4975,1.6535
4976,1.6461
4977,1.641
4978,1.6298
4979,1.636
4980,1.6541
4981,1.6552
4982,1.6488
4983,1.6463
4984,1.649
4985,1.6594
4986,1.657
4987,1.6574
4988,1.6564
4989,1.6553
4990,1.6639
4991,1.6736
4992,1.6755
4993,1.6777
4994,1.6707
4995,1.6728
4996,1.679
4997,1.6614
4998,1.6561
4999,1.6671
5000,1.6896
5001,1.6842
5002,1.6657
5003,1.6744
5004,1.6769
5005,1.6768
5006,1.6733
5007,1.671
5008,1.6772
5009,1.6708
5010,1.6699
5011,1.6651
5012,1.6583
5013,1.6417
5014,1.644
5015,1.6515
5016,1.6484
5017,1.6436
5018,1.6337
5019,1.6337
5020,1.6413
5021,1.6428
5022,1.6396
5023,1.6425
5024,1.6404
5025,1.6318
5026,1.6446
5027,1.6542
5028,1.654
5029,1.6526
5030,1.6481
5031,1.6374
5032,1.6339
5033,1.643
5034,1.6434
5035,1.6441
5036,1.6391
5037,1.6341
5038,1.6352
5039,1.6437
5040,1.6471
5041,1.6495
5042,1.6383
5043,1.6402
5044,1.6449
5045,1.6517
5046,1.6706
5047,1.6772
5048,1.6739
5049,1.6659
5050,1.663
5051,1.6704
5052,1.6701
5053,1.6688
5054,1.6715
5055,1.6679
5056,1.6768
5057,1.6641
5058,1.6575
5059,1.6305
5060,1.6261
5061,1.6266
5062,1.6202
5063,1.6107
5064,1.6106
5065,1.6277
5066,1.6476
5067,1.6531
5068,1.6481
5069,1.6473
5070,1.653
5071,1.6435
5072,1.6476
5073,1.6494
5074,1.6512
5075,1.6529
5076,1.6463
5077,1.642
5078,1.6378
5079,1.6357
5080,1.6418
5081,1.6337
5082,1.6363
5083,1.6392
5084,1.6328
5085,1.6358
5086,1.6283
5087,1.6262
5088,1.6301
5089,1.6294
5090,1.6341
5091,1.636
5092,1.6338
5093,1.6301
5094,1.6238
5095,1.6129
5096,1.6008
5097,1.606
5098,1.6028
5099,1.6087
5100,1.6176
5101,1.6181
5102,1.6081
5103,1.6102
5104,1.609
5105,1.6156
5106,1.6267
5107,1.6266
5108,1.6342
5109,1.6218
5110,1.6241
5111,1.6303
5112,1.6319
5113,1.6309
5114,1.6297
5115,1.6338
5116,1.6453
5117,1.6338
5118,1.6228
5119,1.6212
5120,1.616
5121,1.6162
5122,1.607
5123,1.5916
5124,1.6021
5125,1.6103
5126,1.6056
5127,1.614
5128,1.6154
5129,1.6165
5130,1.6109
5131,1.6136
5132,1.6114
5133,1.6154
5134,1.6062
5135,1.6104
5136,1.6158
5137,1.6123
5138,1.6156
5139,1.6146
5140,1.6098
5141,1.6094
5142,1.6199
5143,1.6264
5144,1.6373
5145,1.6329
5146,1.6307
5147,1.625
5148,1.6197
5149,1.6198
5150,1.6217
5151,1.6268
5152,1.6204
5153,1.6196
5154,1.6121
5155,1.6027
5156,1.5966
5157,1.6029
5158,1.5989
5159,1.5996
5160,1.604
5161,1.6113
5162,1.612
5163,1.6069
5164,1.6092
5165,1.6069
5166,1.607
5167,1.6041
5168,1.6085
5169,1.6147
5170,1.6169
5171,1.6017
5172,1.5968
5173,1.5981
5174,1.5986
5175,1.5931
5176,1.5946
5177,1.5853
5178,1.5873
5179,1.5949
5180,1.5883
5181,1.5872
5182,1.584
5183,1.5837
5184,1.5824
5185,1.5818
5186,1.5747
5187,1.5661
5188,1.5639
5189,1.5591
5190,1.5624
5191,1.5635
5192,1.5699
5193,1.575
5194,1.5721
5195,1.5664
5196,1.5761
5197,1.5775
5198,1.5865
5199,1.5811
5200,1.5957
5201,1.5911
5202,1.5925
5203,1.6152
5204,1.6234
5205,1.6177
5206,1.6188
5207,1.6252
5208,1.6194
5209,1.6187
5210,1.6069
5211,1.617
5212,1.6145
5213,1.6135
5214,1.6091
5215,1.6073
5216,1.6038
5217,1.6095
5218,1.6233
5219,1.6213
5220,1.6147
5221,1.6003
5222,1.5915
5223,1.5892
5224,1.5907
5225,1.6115
5226,1.6075
5227,1.6143
5228,1.6076
5229,1.6073
5230,1.61
5231,1.6188
5232,1.6281
5233,1.621
5234,1.606
5235,1.6048
5236,1.6104
5237,1.6216
5238,1.6209
5239,1.6193
5240,1.6287
5241,1.636
5242,1.6372
5243,1.6395
5244,1.6423
5245,1.6473
5246,1.641
5247,1.6434
5248,1.6511
5249,1.6507
5250,1.6498
5251,1.6533
5252,1.651
5253,1.6517
5254,1.6506
5255,1.6519
5256,1.6511
5257,1.6556
5258,1.6681
5259,1.6672
5260,1.667
5261,1.665
5262,1.674
5263,1.6617
5264,1.6611
5265,1.6521
5266,1.6453
5267,1.6375
5268,1.6378
5269,1.6391
5270,1.6431
5271,1.6409
5272,1.6366
5273,1.6226
5274,1.6159
5275,1.6207
5276,1.6259
5277,1.6227
5278,1.615
5279,1.6205
5280,1.6179
5281,1.6249
5282,1.6155
5283,1.6156
5284,1.6193
5285,1.6247
5286,1.6114
5287,1.6137
5288,1.6039
5289,1.5996
5290,1.5906
5291,1.5961
5292,1.5982
5293,1.6004
5294,1.6159
5295,1.622
5296,1.6236
5297,1.6225
5298,1.6213
5299,1.6216
5300,1.6136
5301,1.6059
5302,1.6113
5303,1.6076
5304,1.6034
5305,1.6094
5306,1.606
5307,1.6148
5308,1.617
5309,1.6155
5310,1.6104
5311,1.6332
5312,1.6363
5313,1.6453
5314,1.6354
5315,1.6359
5316,1.645
5317,1.6448
5318,1.6484
5319,1.6338
5320,1.6301
5321,1.636
5322,1.6386
5323,1.6473
5324,1.6487
5325,1.6505
5326,1.6484
5327,1.6398
5328,1.6368
5329,1.6205
5330,1.6217
5331,1.6166
5332,1.6077
5333,1.6062
5334,1.591
5335,1.5922
5336,1.6139
5337,1.613
5338,1.6077
5339,1.5974
5340,1.5913
5341,1.6
5342,1.6037
5343,1.6093
5344,1.6
5345,1.6014
5346,1.618
5347,1.6075
5348,1.6042
5349,1.5961
5350,1.5918
5351,1.581
5352,1.587
5353,1.582
5354,1.5833
5355,1.5762
5356,1.5843
5357,1.5855
5358,1.5853
5359,1.5823
5360,1.5822
5361,1.5742
5362,1.5751
5363,1.5804
5364,1.5752
5365,1.5698
5366,1.5812
5367,1.5715
5368,1.5857
5369,1.5936
5370,1.5962
5371,1.5902
5372,1.5896
5373,1.5983
5374,1.5997
5375,1.5997
5376,1.6001
5377,1.5941
5378,1.5863
5379,1.5863
5380,1.5871
5381,1.5925
5382,1.5914
5383,1.5932
5384,1.5918
5385,1.5906
5386,1.5816
5387,1.5837
5388,1.5843
5389,1.5834
5390,1.5862
5391,1.5826
5392,1.5731
5393,1.5715
5394,1.5726
5395,1.5548
5396,1.5378
5397,1.5407
5398,1.5436
5399,1.5329
5400,1.5114
5401,1.5258
5402,1.5258
5403,1.5077
5404,1.5026
5405,1.4942
5406,1.4977
5407,1.507
5408,1.491
5409,1.4854
5410,1.4867
5411,1.4973
5412,1.5108
5413,1.5087
5414,1.5054
5415,1.5187
5416,1.5226
5417,1.5348
5418,1.5305
5419,1.5207
5420,1.5158
5421,1.5233
5422,1.5239
5423,1.5147
5424,1.5177
5425,1.5266
5426,1.5237
5427,1.5191
5428,1.5101
5429,1.5229
5430,1.5137
5431,1.5122
5432,1.5112
5433,1.523
5434,1.5322
5435,1.5258
5436,1.5249
5437,1.5264
5438,1.5239
5439,1.526
5440,1.526
5441,1.5244
5442,1.5248
5443,1.5252
5444,1.5114
5445,1.5131
5446,1.505
5447,1.5069
5448,1.5061
5449,1.514
5450,1.5234
5451,1.5243
5452,1.5284
5453,1.5276
5454,1.5256
5455,1.5139
5456,1.5071
5457,1.5093
5458,1.5031
5459,1.5052
5460,1.5149
5461,1.5175
5462,1.5128
5463,1.5102
5464,1.5087
5465,1.5121
5466,1.515
5467,1.5155
5468,1.5076
5469,1.5069
5470,1.5023
5471,1.5001
5472,1.4925
5473,1.4883
5474,1.4892
5475,1.4822
5476,1.4675
5477,1.4628
5478,1.4617
5479,1.4669
5480,1.4671
5481,1.457
5482,1.458
5483,1.4417
5484,1.4298
5485,1.4252
5486,1.4129
5487,1.4185
5488,1.4154
5489,1.4131
5490,1.4076
5491,1.4136
5492,1.4206
5493,1.4297
5494,1.4649
5495,1.4594
5496,1.4639
5497,1.4699
5498,1.4723
5499,1.4857
5500,1.4763
5501,1.4645
5502,1.4651
5503,1.4604
5504,1.4543
5505,1.4556
5506,1.4555
5507,1.4722
5508,1.4751
5509,1.4678
5510,1.4522
5511,1.4461
5512,1.4591
5513,1.4484
5514,1.4516
5515,1.4586
5516,1.4563
5517,1.4423
5518,1.4386
5519,1.4575
5520,1.4603
5521,1.4594
5522,1.455
5523,1.4551
5524,1.4564
5525,1.4421
5526,1.4392
5527,1.4342
5528,1.433
5529,1.4383
5530,1.4475
5531,1.4373
5532,1.4381
5533,1.4319
5534,1.433
5535,1.4339
5536,1.4267
5537,1.4229
5538,1.4097
5539,1.4109
5540,1.4262
5541,1.4284
5542,1.4316
5543,1.4266
5544,1.4406
5545,1.461
5546,1.4518
5547,1.444
5548,1.4492
5549,1.4569
5550,1.463
5551,1.456
5552,1.4578
5553,1.4754
5554,1.4796
5555,1.4712
5556,1.4684
5557,1.479
5558,1.4792
5559,1.4812
5560,1.4922
5561,1.4939
5562,1.4992
5563,1.4982
5564,1.5069
5565,1.4953
5566,1.493
5567,1.4965
5568,1.4884
5569,1.4876
5570,1.4924
5571,1.4761
5572,1.4778
5573,1.4691
5574,1.4717
5575,1.4732
5576,1.4647
5577,1.4575
5578,1.4676
5579,1.455
5580,1.4572
5581,1.4551
5582,1.4535
5583,1.4567
5584,1.4579
5585,1.4723
5586,1.4641
5587,1.4712
5588,1.4568
5589,1.4577
5590,1.4412
5591,1.4418
5592,1.4475
5593,1.4479
5594,1.4561
5595,1.4468
5596,1.4477
5597,1.4415
5598,1.4408
5599,1.44
5600,1.4413
5601,1.4429
5602,1.4352
5603,1.4355
5604,1.4363
5605,1.4481
5606,1.4673
5607,1.4622
5608,1.46
5609,1.4547
5610,1.461
5611,1.4608
5612,1.4725
5613,1.4461
5614,1.4417
5615,1.4373
5616,1.4225
5617,1.419
5618,1.4215
5619,1.4214
5620,1.4121
5621,1.4225
5622,1.4268
5623,1.43
5624,1.4285
5625,1.4295
5626,1.4153
5627,1.4138
5628,1.4201
5629,1.4261
5630,1.421
5631,1.4312
5632,1.4414
5633,1.4307
5634,1.4274
5635,1.4317
5636,1.4248
5637,1.4116
5638,1.4261
5639,1.4308
5640,1.4289
5641,1.4252
5642,1.4293
5643,1.4303
5644,1.427
5645,1.4215
5646,1.4224
5647,1.4233
5648,1.4224
5649,1.4261
5650,1.4204
5651,1.4098
5652,1.4106
5653,1.4087
5654,1.4068
5655,1.41
5656,1.4164
5657,1.4171
5658,1.4169
5659,1.4234
5660,1.4153
5661,1.4114
5662,1.3963
5663,1.4065
5664,1.4042
5665,1.409
5666,1.4056
5667,1.4
5668,1.405
5669,1.3942
5670,1.3784
5671,1.3729
5672,1.3639
5673,1.3561
5674,1.3594
5675,1.3684
5676,1.385
5677,1.3828
5678,1.3828
5679,1.381
5680,1.3734
5681,1.3917
5682,1.3898
5683,1.3926
5684,1.3949
5685,1.3924
5686,1.3894
5687,1.3876
5688,1.396
5689,1.3874
5690,1.3869
5691,1.3802
5692,1.3881
5693,1.3902
5694,1.3922
5695,1.3946
5696,1.3867
5697,1.3813
5698,1.3803
5699,1.3805
5700,1.3955
5701,1.3947
5702,1.4063
5703,1.3982
5704,1.3992
5705,1.4067
5706,1.407
5707,1.4031
5708,1.4047
5709,1.4053
5710,1.411
5711,1.4141
5712,1.4128
5713,1.4028
5714,1.4
5715,1.3972
5716,1.4043
5717,1.4096
5718,1.405
5719,1.4038
5720,1.42
5721,1.4246
5722,1.426
5723,1.4253
5724,1.4292
5725,1.4357
5726,1.4274
5727,1.4272
5728,1.429
5729,1.4324
5730,1.4301
5731,1.4313
5732,1.4332
5733,1.4274
5734,1.4341
5735,1.4348
5736,1.4426
5737,1.4392
5738,1.4494
5739,1.4428
5740,1.4476
5741,1.4475
5742,1.4447
5743,1.4391
5744,1.4424
5745,1.4407
5746,1.4334
5747,1.4403
5748,1.4453
5749,1.4493
5750,1.4497
5751,1.4448
5752,1.4523
5753,1.4401
5754,1.4495
5755,1.4504
5756,1.4534
5757,1.4463
5758,1.4386
5759,1.4225
5760,1.4164
5761,1.4235
5762,1.42
5763,1.4204
5764,1.425
5765,1.4182
5766,1.4122
5767,1.4019
5768,1.3957
5769,1.3988
5770,1.4045
5771,1.4072
5772,1.4255
5773,1.4302
5774,1.4285
5775,1.4369
5776,1.4368
5777,1.4314
5778,1.4342
5779,1.4379
5780,1.4306
5781,1.4339
5782,1.4324
5783,1.4194
5784,1.4182
5785,1.4081
5786,1.4068
5787,1.4118
5788,1.4171
5789,1.413
5790,1.4129
5791,1.4081
5792,1.4121
5793,1.4135
5794,1.4236
5795,1.4223
5796,1.4258
5797,1.4209
5798,1.4218
5799,1.4173
5800,1.4252
5801,1.4312
5802,1.4081
5803,1.4088
5804,1.4183
5805,1.4201
5806,1.425
5807,1.4315
5808,1.4301
5809,1.4224
5810,1.4207
5811,1.4115
5812,1.4121
5813,1.4259
5814,1.4207
5815,1.4275
5816,1.4186
5817,1.4161
5818,1.4136
5819,1.4087
5820,1.4112
5821,1.4081
5822,1.414
5823,1.4114
5824,1.416
5825,1.4117
5826,1.4064
5827,1.4072
5828,1.4069
5829,1.4083
5830,1.4
5831,1.3979
5832,1.3952
5833,1.3824
5834,1.3816
5835,1.3833
5836,1.3854
5837,1.3859
5838,1.3865
5839,1.3893
5840,1.3903
5841,1.3865
5842,1.3836
5843,1.3886
5844,1.3931
5845,1.3993
5846,1.402
5847,1.3996
5848,1.4033
5849,1.3991
5850,1.3999
5851,1.3988
5852,1.3967
5853,1.4024
5854,1.4002
5855,1.3978
5856,1.3888
5857,1.3869
5858,1.3913
5859,1.3938
5860,1.3935
5861,1.3942
5862,1.398
5863,1.3962
5864,1.3963
5865,1.3859
5866,1.3874
5867,1.3956
5868,1.4005
5869,1.3999
5870,1.4001
5871,1.4012
5872,1.4022
5873,1.402
5874,1.4015
5875,1.402
5876,1.3979
5877,1.3999
5878,1.4162
5879,1.4119
5880,1.4124
5881,1.4096
5882,1.4062
5883,1.4059
5884,1.4089
5885,1.4119
5886,1.4099
5887,1.411
5888,1.4124
5889,1.4143
5890,1.419
5891,1.419
5892,1.4219
5893,1.4208
5894,1.4208
5895,1.4267
5896,1.4268
5897,1.4291
5898,1.4294
5899,1.4335
5900,1.4351
5901,1.4386
5902,1.435
5903,1.4295
5904,1.4289
5905,1.4316
5906,1.4294
5907,1.4198
5908,1.4256
5909,1.4245
5910,1.4311
5911,1.4287
5912,1.4247
5913,1.4282
5914,1.422
5915,1.4271
5916,1.4258
5917,1.4328
5918,1.4305
5919,1.4342
5920,1.4321
5921,1.4238
5922,1.4279
5923,1.4295
5924,1.4299
5925,1.4326
5926,1.4383
5927,1.44
5928,1.4443
5929,1.4445
5930,1.4538
5931,1.4563
5932,1.4658
5933,1.4664
5934,1.4712
5935,1.4658
5936,1.4912
5937,1.4883
5938,1.4917
5939,1.4948
5940,1.4967
5941,1.4917
5942,1.4904
5943,1.4861
5944,1.5004
5945,1.5127
5946,1.5113
5947,1.5144
5948,1.5152
5949,1.5303
5950,1.5382
5951,1.5332
5952,1.536
5953,1.5435
5954,1.5408
5955,1.53
5956,1.539
5957,1.5435
5958,1.5326
5959,1.5247
5960,1.539
5961,1.5294
5962,1.5243
5963,1.5362
5964,1.5334
5965,1.5051
5966,1.5004
5967,1.4983
5968,1.4923
5969,1.4983
5970,1.4995
5971,1.5109
5972,1.5016
5973,1.5044
5974,1.4955
5975,1.4928
5976,1.4978
5977,1.4907
5978,1.4886
5979,1.4987
5980,1.5054
5981,1.5173
5982,1.5156
5983,1.5185
5984,1.5315
5985,1.5322
5986,1.5342
5987,1.5281
5988,1.5263
5989,1.521
5990,1.5152
5991,1.5218
5992,1.5288
5993,1.5127
5994,1.5032
5995,1.5177
5996,1.5227
5997,1.5224
5998,1.5281
5999,1.5253
6000,1.5288
6001,1.5271
6002,1.5199
6003,1.5393
6004,1.5368
6005,1.5323
6006,1.5363
6007,1.5346
6008,1.5343
6009,1.5243
6010,1.5254
6011,1.5287
6012,1.5272
6013,1.5246
6014,1.5224
6015,1.5209
6016,1.5201
6017,1.5165
6018,1.513
6019,1.5156
6020,1.5177
6021,1.516
6022,1.5234
6023,1.5213
6024,1.5253
6025,1.5232
6026,1.5297
6027,1.5298
6028,1.5197
6029,1.5274
6030,1.5244
6031,1.5428
6032,1.552
6033,1.551
6034,1.5504
6035,1.5485
6036,1.5429
6037,1.5425
6038,1.5441
6039,1.5516
6040,1.5384
6041,1.5418
6042,1.5447
6043,1.5295
6044,1.5242
6045,1.5074
6046,1.5156
6047,1.5184
6048,1.5171
6049,1.5296
6050,1.5335
6051,1.5329
6052,1.5371
6053,1.5388
6054,1.5343
6055,1.5382
6056,1.5403
6057,1.5519
6058,1.5504
6059,1.56
6060,1.5621
6061,1.5633
6062,1.5653
6063,1.5545
6064,1.5577
6065,1.5636
6066,1.5659
6067,1.5709
6068,1.5604
6069,1.5652
6070,1.5738
6071,1.5689
6072,1.562
6073,1.569
6074,1.5707
6075,1.5676
6076,1.5716
6077,1.566
6078,1.5681
6079,1.5792
6080,1.57
6081,1.5711
6082,1.5747
6083,1.584
6084,1.592
6085,1.5947
6086,1.6018
6087,1.6094
6088,1.6091
6089,1.6057
6090,1.6012
6091,1.6091
6092,1.6079
6093,1.6052
6094,1.5987
6095,1.5954
6096,1.5838
6097,1.5827
6098,1.5882
6099,1.5796
6100,1.567
6101,1.5589
6102,1.5618
6103,1.5611
6104,1.5594
6105,1.5536
6106,1.54
6107,1.5506
6108,1.5467
6109,1.5433
6110,1.5486
6111,1.5495
6112,1.5679
6113,1.5693
6114,1.5708
6115,1.5651
6116,1.5718
6117,1.5782
6118,1.5721
6119,1.5526
6120,1.5427
6121,1.5297
6122,1.5286
6123,1.5306
6124,1.529
6125,1.541
6126,1.5372
6127,1.5389
6128,1.5367
6129,1.5335
6130,1.5464
6131,1.541
6132,1.5356
6133,1.5364
6134,1.5264
6135,1.5162
6136,1.5157
6137,1.5208
6138,1.5384
6139,1.5368
6140,1.5405
6141,1.5366
6142,1.5423
6143,1.5457
6144,1.5443
6145,1.5484
6146,1.56
6147,1.5571
6148,1.5569
6149,1.5568
6150,1.5642
6151,1.5767
6152,1.5693
6153,1.5801
6154,1.5578
6155,1.5643
6156,1.566
6157,1.5741
6158,1.5714
6159,1.583
6160,1.5877
6161,1.5878
6162,1.5998
6163,1.5975
6164,1.6079
6165,1.5972
6166,1.602
6167,1.6054
6168,1.5976
6169,1.613
6170,1.602
6171,1.5973
6172,1.5934
6173,1.5943
6174,1.616
6175,1.6251
6176,1.6103
6177,1.61
6178,1.6287
6179,1.6292
6180,1.6274
6181,1.6403
6182,1.6484
6183,1.6373
6184,1.6358
6185,1.6274
6186,1.6272
6187,1.6249
6188,1.6342
6189,1.6251
6190,1.6127
6191,1.6131
6192,1.6251
6193,1.6279
6194,1.6338
6195,1.63
6196,1.613
6197,1.5985
6198,1.5934
6199,1.5938
6200,1.5966
6201,1.5903
6202,1.5679
6203,1.5618
6204,1.5564
6205,1.5504
6206,1.5629
6207,1.5663
6208,1.5751
6209,1.5775
6210,1.5861
6211,1.5888
6212,1.5898
6213,1.581
6214,1.5717
6215,1.5711
6216,1.5732
6217,1.5701
6218,1.5749
6219,1.5802
6220,1.5723
6221,1.565
6222,1.5641
6223,1.5706
6224,1.5625
6225,1.5563
6226,1.5534
6227,1.547
6228,1.5543
6229,1.5438
6230,1.5357
6231,1.5336
6232,1.5351
6233,1.54
6234,1.5427
6235,1.5327
6236,1.5322
6237,1.5303
6238,1.5415
6239,1.5452
6240,1.5456
6241,1.5479
6242,1.5494
6243,1.5536
6244,1.5635
6245,1.5616
6246,1.5482
6247,1.5603
6248,1.5737
6249,1.5876
6250,1.6046
6251,1.6099
6252,1.6132
6253,1.6189
6254,1.6166
6255,1.6167
6256,1.6173
6257,1.6237
6258,1.6253
6259,1.622
6260,1.6263
6261,1.6217
6262,1.6146
6263,1.6175
6264,1.6213
6265,1.6201
6266,1.6209
6267,1.6222
6268,1.6351
6269,1.6267
6270,1.6313
6271,1.6313
6272,1.6419
6273,1.6446
6274,1.6489
6275,1.6472
6276,1.6459
6277,1.6512
6278,1.6515
6279,1.6481
6280,1.6316
6281,1.6293
6282,1.6335
6283,1.6227
6284,1.6221
6285,1.6258
6286,1.6198
6287,1.6297
6288,1.6386
6289,1.6368
6290,1.6411
6291,1.6504
6292,1.6509
6293,1.6555
6294,1.6553
6295,1.6465
6296,1.6474
6297,1.6592
6298,1.6648
6299,1.6709
6300,1.673
6301,1.6798
6302,1.6795
6303,1.6719
6304,1.6768
6305,1.6838
6306,1.6916
6307,1.6968
6308,1.692
6309,1.6959
6310,1.697
6311,1.7009
6312,1.7124
6313,1.7182
6314,1.7129
6315,1.7121
6316,1.717
6317,1.7242
6318,1.7212
6319,1.7294
6320,1.7402
6321,1.7381
6322,1.7552
6323,1.7694
6324,1.7678
6325,1.7763
6326,1.794
6327,1.7975
6328,1.7964
6329,1.7852
6330,1.7694
6331,1.7495
6332,1.7341
6333,1.7643
6334,1.7783
6335,1.7894
6336,1.7776
6337,1.7652
6338,1.7656
6339,1.7753
6340,1.7602
6341,1.7668
6342,1.7652
6343,1.783
6344,1.7742
6345,1.7845
6346,1.7926
6347,1.8029
6348,1.8095
6349,1.8129
6350,1.8355
6351,1.8321
6352,1.834
6353,1.845
6354,1.8482
6355,1.8329
6356,1.8133
6357,1.8107
6358,1.8286
6359,1.825
6360,1.8024
6361,1.7995
6362,1.8108
6363,1.7906
6364,1.7673
6365,1.7656
6366,1.7901
6367,1.786
6368,1.7804
6369,1.7445
6370,1.7427
6371,1.7369
6372,1.7384
6373,1.7619
6374,1.7534
6375,1.7752
6376,1.7761
6377,1.7881
6378,1.7873
6379,1.7758
6380,1.7535
6381,1.7531
6382,1.7598
6383,1.7678
6384,1.7783
6385,1.7977
6386,1.7739
6387,1.7584
6388,1.7743
6389,1.7836
6390,1.778
6391,1.7581
6392,1.7321
6393,1.7272
6394,1.7483
6395,1.7537
6396,1.7393
6397,1.7201
6398,1.7162
6399,1.7156
6400,1.7346
6401,1.7373
6402,1.7225
6403,1.7251
6404,1.7221
6405,1.7432
6406,1.7374
6407,1.7432
6408,1.7375
6409,1.7277
6410,1.7079
6411,1.726
6412,1.7144
6413,1.7109
6414,1.7176
6415,1.7202
6416,1.7314
6417,1.7203
6418,1.7384
6419,1.7396
6420,1.7583
6421,1.7614
6422,1.7811
6423,1.7794
6424,1.7836
6425,1.7888
6426,1.7886
6427,1.7842
6428,1.7834
6429,1.7828
6430,1.7759
6431,1.7791
6432,1.7684
6433,1.7679
6434,1.7686
6435,1.7768
6436,1.782
6437,1.7873
6438,1.7789
6439,1.7703
6440,1.77
6441,1.7712
6442,1.7717
6443,1.7801
6444,1.7599
6445,1.7654
6446,1.7661
6447,1.7759
6448,1.7767
6449,1.7883
6450,1.8017
6451,1.806
6452,1.8016
6453,1.8112
6454,1.8047
6455,1.8047
6456,1.8021
6457,1.8219
6458,1.8199
6459,1.8037
6460,1.7872
6461,1.7969
6462,1.7826
6463,1.7907
6464,1.7754
6465,1.774
6466,1.7666
6467,1.7682
6468,1.7752
6469,1.7717
6470,1.7728
6471,1.7721
6472,1.7914
6473,1.7867
6474,1.7868
6475,1.7768
6476,1.7715
6477,1.7911
6478,1.7892
6479,1.7771
6480,1.7716
6481,1.7814
6482,1.7711
6483,1.7645
6484,1.7471
6485,1.7497
6486,1.7454
6487,1.7454
6488,1.7501
6489,1.7448
6490,1.7417
6491,1.7295
6492,1.7339
6493,1.7262
6494,1.7364
6495,1.7366
6496,1.7533
6497,1.7482
6498,1.7525
6499,1.7285
6500,1.741
6501,1.7425
6502,1.7347
6503,1.7449
6504,1.746
6505,1.7518
6506,1.757
6507,1.7609
6508,1.766
6509,1.7554
6510,1.7655
6511,1.7524
6512,1.7398
6513,1.7384
6514,1.7365
6515,1.7398
6516,1.7509
6517,1.7521
6518,1.7431
6519,1.7442
6520,1.7516
6521,1.7614
6522,1.757
6523,1.761
6524,1.7697
6525,1.7836
6526,1.7833
6527,1.7951
6528,1.794
6529,1.7938
6530,1.7873
6531,1.7902
6532,1.7914
6533,1.7949
6534,1.8052
6535,1.8
6536,1.808
6537,1.8172
6538,1.8165
6539,1.8075
6540,1.8046
6541,1.8126
6542,1.813
6543,1.8172
6544,1.8193
6545,1.8144
6546,1.8225
6547,1.8223
6548,1.8359
6549,1.8456
6550,1.855
6551,1.8602
6552,1.8614
6553,1.8779
6554,1.893
6555,1.8898
6556,1.901
6557,1.9052
6558,1.9069
6559,1.8919
6560,1.8817
6561,1.8792
6562,1.8872
6563,1.8895
6564,1.9099
6565,1.8993
6566,1.9012
6567,1.9147
6568,1.8924
6569,1.8801
6570,1.8874
6571,1.8945
6572,1.8838
6573,1.8898
6574,1.888
6575,1.8526
6576,1.8581
6577,1.8457
6578,1.8388
6579,1.8458
6580,1.8485
6581,1.8643
6582,1.8521
6583,1.8409
6584,1.8322
6585,1.8384
6586,1.848
6587,1.8413
6588,1.8401
6589,1.8463
6590,1.8358
6591,1.852
6592,1.857
6593,1.8536
6594,1.8567
6595,1.8509
6596,1.8559
6597,1.851
6598,1.857
6599,1.8374
6600,1.8276
6601,1.8282
6602,1.8417
6603,1.8358
6604,1.8575
6605,1.8579
6606,1.8503
6607,1.8625
6608,1.8665
6609,1.869
6610,1.8767
6611,1.8762
6612,1.8782
6613,1.8864
6614,1.8968
6615,1.8911
6616,1.8807
6617,1.8794
6618,1.897
6619,1.8852
6620,1.9025
6621,1.8929
6622,1.8959
6623,1.8998
6624,1.8855
6625,1.8896
6626,1.9019
6627,1.8978
6628,1.89
6629,1.8711
6630,1.8746
6631,1.8514
6632,1.8473
6633,1.8518
6634,1.8613
6635,1.8685
6636,1.8664
6637,1.8502
6638,1.8548
6639,1.8548
6640,1.8551
6641,1.8538
6642,1.869
6643,1.8646
6644,1.8706
6645,1.8591
6646,1.8704
6647,1.8799
6648,1.8913
6649,1.8921
6650,1.8886
6651,1.8923
6652,1.8891
6653,1.8819
6654,1.8848
6655,1.8878
6656,1.8878
6657,1.8697
6658,1.8811
6659,1.8832
6660,1.8727
6661,1.8638
6662,1.8647
6663,1.8557
6664,1.8468
6665,1.8385
6666,1.8172
6667,1.8218
6668,1.8167
6669,1.8184
6670,1.8076
6671,1.8125
6672,1.8116
6673,1.8141
6674,1.8048
6675,1.8071
6676,1.8062
6677,1.7979
6678,1.8005
6679,1.7998
6680,1.8031
6681,1.8135
6682,1.8229
6683,1.8032
6684,1.7988
6685,1.787
6686,1.7919
6687,1.8039
6688,1.8041
6689,1.8085
6690,1.8088
6691,1.8114
6692,1.8094
6693,1.8069
6694,1.8092
6695,1.814
6696,1.8056
6697,1.7935
6698,1.7832
6699,1.7635
6700,1.7537
6701,1.7463
6702,1.7501
6703,1.735
6704,1.7298
6705,1.7495
6706,1.7666
6707,1.7488
6708,1.7549
6709,1.7482
6710,1.7455
6711,1.7323
6712,1.7254
6713,1.7407
6714,1.7395
6715,1.7402
6716,1.7377
6717,1.7386
6718,1.7487
6719,1.7569
6720,1.7661
6721,1.767
6722,1.7757
6723,1.7747
6724,1.7707
6725,1.7841
6726,1.7816
6727,1.793
6728,1.8045
6729,1.8114
6730,1.8053
6731,1.806
6732,1.8062
6733,1.7904
6734,1.7885
6735,1.7993
6736,1.7955
6737,1.7953
6738,1.7992
6739,1.8058
6740,1.7821
6741,1.7947
6742,1.8226
6743,1.8345
6744,1.8366
6745,1.8368
6746,1.8338
6747,1.836
6748,1.8353
6749,1.8171
6750,1.8169
6751,1.822
6752,1.7989
6753,1.7995
6754,1.8008
6755,1.8004
6756,1.8094
6757,1.7868
6758,1.7742
6759,1.7718
6760,1.7634
6761,1.7602
6762,1.7605
6763,1.7693
6764,1.7557
6765,1.7617
6766,1.7622
6767,1.7751
6768,1.7622
6769,1.755
6770,1.7491
6771,1.7538
6772,1.7509
6773,1.7679
6774,1.7545
6775,1.749
6776,1.7621
6777,1.7714
6778,1.7754
6779,1.7696
6780,1.7861
6781,1.7779
6782,1.7856
6783,1.7785
6784,1.7725
6785,1.7639
6786,1.7771
6787,1.7785
6788,1.7526
6789,1.7449
6790,1.7413
6791,1.743
6792,1.7497
6793,1.7429
6794,1.741
6795,1.7359
6796,1.7185
6797,1.7242
6798,1.7168
6799,1.7223
6800,1.7153
6801,1.7246
6802,1.7271
6803,1.7195
6804,1.7239
6805,1.7208
6806,1.7337
6807,1.7343
6808,1.7347
6809,1.7409
6810,1.7417
6811,1.7356
6812,1.7521
6813,1.7583
6814,1.7751
6815,1.7727
6816,1.7764
6817,1.7656
6818,1.7748
6819,1.7669
6820,1.7646
6821,1.745
6822,1.7424
6823,1.7382
6824,1.7326
6825,1.7313
6826,1.7225
6827,1.7449
6828,1.7649
6829,1.7603
6830,1.7762
6831,1.768
6832,1.7692
6833,1.7657
6834,1.7669
6835,1.7752
6836,1.7723
6837,1.7649
6838,1.768
6839,1.7676
6840,1.7679
6841,1.7904
6842,1.7894
6843,1.7922
6844,1.7922
6845,1.778
6846,1.7742
6847,1.7833
6848,1.7856
6849,1.7854
6850,1.7677
6851,1.7587
6852,1.7492
6853,1.7501
6854,1.748
6855,1.7538
6856,1.7524
6857,1.7396
6858,1.7536
6859,1.7458
6860,1.7507
6861,1.7551
6862,1.7531
6863,1.7498
6864,1.7608
6865,1.7539
6866,1.7488
6867,1.7604
6868,1.7624
6869,1.7559
6870,1.7608
6871,1.7608
6872,1.7449
6873,1.7452
6874,1.7468
6875,1.736
6876,1.7388
6877,1.7548
6878,1.7542
6879,1.7632
6880,1.762
6881,1.7638
6882,1.7563
6883,1.7557
6884,1.7438
6885,1.7495
6886,1.7566
6887,1.7595
6888,1.7431
6889,1.7553
6890,1.7442
6891,1.7476
6892,1.7656
6893,1.7597
6894,1.7623
6895,1.7524
6896,1.7546
6897,1.7578
6898,1.7619
6899,1.7622
6900,1.7879
6901,1.7989
6902,1.7877
6903,1.7929
6904,1.7929
6905,1.7983
6906,1.7979
6907,1.8128
6908,1.8272
6909,1.8489
6910,1.8501
6911,1.8581
6912,1.868
6913,1.8676
6914,1.8744
6915,1.8728
6916,1.8882
6917,1.8984
6918,1.8903
6919,1.894
6920,1.8943
6921,1.8992
6922,1.8799
6923,1.8899
6924,1.8923
6925,1.8769
6926,1.881
6927,1.8649
6928,1.8956
6929,1.8813
6930,1.8788
6931,1.8956
6932,1.8866
6933,1.8702
6934,1.8655
6935,1.85
6936,1.8544
6937,1.8539
6938,1.8478
6939,1.859
6940,1.8624
6941,1.8625
6942,1.8505
6943,1.854
6944,1.8562
6945,1.8418
6946,1.8331
6947,1.8316
6948,1.8371
6949,1.8299
6950,1.8269
6951,1.863
6952,1.8575
6953,1.8607
6954,1.8481
6955,1.8514
6956,1.8655
6957,1.8554
6958,1.8566
6959,1.8467
6960,1.8567
6961,1.8483
6962,1.8334
6963,1.8386
6964,1.853
6965,1.8635
6966,1.8704
6967,1.8622
6968,1.8593
6969,1.8588
6970,1.876
6971,1.8765
6972,1.8777
6973,1.8779
6974,1.8891
6975,1.8962
6976,1.9166
6977,1.9162
6978,1.9136
6979,1.9145
6980,1.8978
6981,1.9031
6982,1.8984
6983,1.9013
6984,1.9056
6985,1.899
6986,1.8856
6987,1.9031
6988,1.8947
6989,1.9001
6990,1.8972
6991,1.8916
6992,1.8986
6993,1.9107
6994,1.9059
6995,1.9076
6996,1.9089
6997,1.897
6998,1.8853
6999,1.8782
7000,1.8695
7001,1.8669
7002,1.8794
7003,1.878
7004,1.8938
7005,1.881
7006,1.8803
7007,1.8894
7008,1.8912
7009,1.8989
7010,1.9033
7011,1.8999
7012,1.896
7013,1.8896
7014,1.8756
7015,1.8701
7016,1.8855
7017,1.8891
7018,1.8837
7019,1.8769
7020,1.8707
7021,1.8663
7022,1.857
7023,1.8576
7024,1.8581
7025,1.8571
7026,1.8619
7027,1.8703
7028,1.8683
7029,1.8775
7030,1.8816
7031,1.8732
7032,1.8726
7033,1.8779
7034,1.8876
7035,1.8966
7036,1.9018
7037,1.9067
7038,1.9058
7039,1.9059
7040,1.9005
7041,1.8964
7042,1.9082
7043,1.9023
7044,1.8976
7045,1.9108
7046,1.9023
7047,1.8928
7048,1.8874
7049,1.8885
7050,1.894
7051,1.8966
7052,1.8985
7053,1.913
7054,1.9141
7055,1.9308
7056,1.9357
7057,1.9454
7058,1.9471
7059,1.9644
7060,1.9764
7061,1.9755
7062,1.9676
7063,1.9672
7064,1.9614
7065,1.9643
7066,1.9516
7067,1.9633
7068,1.9643
7069,1.9599
7070,1.9482
7071,1.9425
7072,1.9591
7073,1.9621
7074,1.9581
7075,1.9561
7076,1.9514
7077,1.9567
7078,1.9544
7079,1.9695
7080,1.949
7081,1.9401
7082,1.9235
7083,1.9306
7084,1.9364
7085,1.9309
7086,1.9343
7087,1.9532
7088,1.9591
7089,1.9534
7090,1.9633
7091,1.9641
7092,1.9657
7093,1.9675
7094,1.978
7095,1.9585
7096,1.9635
7097,1.9522
7098,1.9507
7099,1.9546
7100,1.9504
7101,1.9628
7102,1.9603
7103,1.9516
7104,1.9602
7105,1.9617
7106,1.9513
7107,1.9414
7108,1.9408
7109,1.9375
7110,1.9545
7111,1.9483
7112,1.9436
7113,1.9412
7114,1.9501
7115,1.9458
7116,1.9461
7117,1.9562
7118,1.9562
7119,1.9581
7120,1.9517
7121,1.9488
7122,1.9355
7123,1.9173
7124,1.9163
7125,1.9212
7126,1.9214
7127,1.9242
7128,1.921
7129,1.9239
7130,1.9252
7131,1.9285
7132,1.9347
7133,1.9381
7134,1.9486
7135,1.9505
7136,1.9573
7137,1.9535
7138,1.9584
7139,1.9551
7140,1.9545
7141,1.9524
7142,1.951
7143,1.9665
7144,1.9673
7145,1.9658
7146,1.962
7147,1.9636
7148,1.9698
7149,1.9705
7150,1.974
7151,1.9811
7152,1.9937
7153,1.9939
7154,1.9909
7155,1.9924
7156,1.9889
7157,1.9905
7158,1.9934
7159,1.9805
7160,1.9903
7161,1.9879
7162,1.9874
7163,1.9783
7164,1.9761
7165,1.9799
7166,1.9778
7167,1.9847
7168,1.9712
7169,1.9707
7170,1.9687
7171,1.9722
7172,1.9709
7173,1.9631
7174,1.9627
7175,1.9579
7176,1.9624
7177,1.976
7178,1.9727
7179,1.9717
7180,1.9691
7181,1.9619
7182,1.9657
7183,1.9662
7184,1.9783
7185,1.9803
7186,1.9794
7187,1.9685
7188,1.9553
7189,1.955
7190,1.9604
7191,1.9602
7192,1.9575
7193,1.9646
7194,1.968
7195,1.974
7196,1.9788
7197,1.9775
7198,1.9808
7199,1.9811
7200,1.9837
7201,1.9812
7202,1.9871
7203,1.9905
7204,1.9975
7205,2.0004
7206,1.9994
7207,1.9941
7208,1.9973
7209,1.9996
7210,2.0078
7211,2.0179
7212,2.013
7213,2.0166
7214,2.0201
7215,2.027
7216,2.0344
7217,2.0329
7218,2.038
7219,2.0405
7220,2.0434
7221,2.0318
7222,2.0284
7223,2.0119
7224,2.0052
7225,2.0135
7226,2.01
7227,2.0136
7228,2.019
7229,2.0104
7230,2.0015
7231,2.0195
7232,2.0091
7233,1.9979
7234,1.9908
7235,1.9798
7236,1.9705
7237,1.9589
7238,1.9625
7239,1.9617
7240,1.9587
7241,1.9668
7242,1.982
7243,1.9863
7244,1.985
7245,1.9897
7246,1.9912
7247,1.9927
7248,1.9942
7249,1.9861
7250,1.9947
7251,1.9973
7252,2.0001
7253,2.002
7254,2.0049
7255,2.0074
7256,2.0046
7257,1.991
7258,1.9801
7259,1.9758
7260,1.9767
7261,1.9912
7262,1.998
7263,1.9994
7264,1.9934
7265,1.9935
7266,2.0009
7267,2.0157
7268,2.0225
7269,2.0207
7270,2.0173
7271,2.0213
7272,2.0224
7273,2.018
7274,2.0137
7275,2.0224
7276,2.0176
7277,2.0126
7278,2.02
7279,2.0097
7280,2.0156
7281,2.0232
7282,2.0208
7283,2.0032
7284,2.0237
7285,2.0208
7286,2.0239
7287,2.0269
7288,2.0352
7289,2.0411
7290,2.0508
7291,2.055
7292,2.0548
7293,2.055
7294,2.0623
7295,2.0784
7296,2.0818
7297,2.0684
7298,2.0318
7299,2.0446
7300,2.0402
7301,2.0201
7302,2.0194
7303,2.0259
7304,2.0384
7305,2.0273
7306,2.0333
7307,2.0266
7308,2.0397
7309,2.0409
7310,2.0419
7311,2.0331
7312,2.0258
7313,2.0367
7314,2.0285
7315,1.9997
7316,1.9972
7317,2.0033
7318,2.0192
7319,2.0109
7320,2.0185
7321,2.0109
7322,1.9948
7323,1.9905
7324,1.9922
7325,1.9794
7326,1.9562
7327,1.9594
7328,1.957
7329,1.9646
7330,1.9683
7331,1.9655
7332,1.9538
7333,1.9454
7334,1.9468
7335,1.9473
7336,1.9452
7337,1.9298
7338,1.9283
7339,1.9257
7340,1.9256
7341,1.9379
7342,1.9314
7343,1.9416
7344,1.9175
7345,1.9079
7346,1.9184
7347,1.9036
7348,1.9275
7349,1.9391
7350,1.9424
7351,1.9427
7352,1.944
7353,1.9422
7354,1.9229
7355,1.9305
7356,1.9187
7357,1.9135
7358,1.8961
7359,1.9012
7360,1.9002
7361,1.9128
7362,1.9136
7363,1.9234
7364,1.9148
7365,1.9045
7366,1.9039
7367,1.8946
7368,1.9122
7369,1.918
7370,1.9212
7371,1.9255
7372,1.9389
7373,1.9394
7374,1.9381
7375,1.931
7376,1.934
7377,1.9388
7378,1.9571
7379,1.9607
7380,1.9624
7381,1.9509
7382,1.9664
7383,1.9735
7384,1.9683
7385,1.9399
7386,1.96
7387,1.9298
7388,1.9253
7389,1.9416
7390,1.9443
7391,1.9523
7392,1.9342
7393,1.9328
7394,1.9221
7395,1.9296
7396,1.944
7397,1.9434
7398,1.9387
7399,1.9178
7400,1.9226
7401,1.927
7402,1.9195
7403,1.9312
7404,1.9131
7405,1.9279
7406,1.9398
7407,1.9511
7408,1.9338
7409,1.9454
7410,1.9319
7411,1.9255
7412,1.9418
7413,1.9479
7414,1.9252
7415,1.9349
7416,1.928
7417,1.9281
7418,1.9304
7419,1.9065
7420,1.9099
7421,1.8991
7422,1.9128
7423,1.8977
7424,1.8914
7425,1.8957
7426,1.9012
7427,1.8966
7428,1.9152
7429,1.9105
7430,1.9274
7431,1.9279
7432,1.9215
7433,1.9288
7434,1.9249
7435,1.9232
7436,1.9122
7437,1.9144
7438,1.9017
7439,1.9024
7440,1.9163
7441,1.9212
7442,1.9023
7443,1.9139
7444,1.8973
7445,1.8951
7446,1.9155
7447,1.9068
7448,1.9101
7449,1.9195
7450,1.9241
7451,1.9098
7452,1.9219
7453,1.9188
7454,1.9381
7455,1.9394
7456,1.9371
7457,1.939
7458,1.9408
7459,1.9323
7460,1.932
7461,1.9207
7462,1.9218
7463,1.9283
7464,1.9283
7465,1.9387
7466,1.9422
7467,1.9539
7468,1.9457
7469,1.9575
7470,1.9465
7471,1.9486
7472,1.9495
7473,1.9499
7474,1.9363
7475,1.9407
7476,1.9438
7477,1.935
7478,1.9333
7479,1.9346
7480,1.9274
7481,1.9203
7482,1.9114
7483,1.9071
7484,1.9012
7485,1.8729
7486,1.873
7487,1.8573
7488,1.8244
7489,1.8347
7490,1.8225
7491,1.8252
7492,1.8216
7493,1.8178
7494,1.834
7495,1.8178
7496,1.799
7497,1.7991
7498,1.7895
7499,1.7849
7500,1.7612
7501,1.7493
7502,1.7392
7503,1.7342
7504,1.729
7505,1.7266
7506,1.7255
7507,1.7163
7508,1.7119
7509,1.7454
7510,1.7507
7511,1.7319
7512,1.7559
7513,1.7807
7514,1.7936
7515,1.8057
7516,1.8184
7517,1.8185
7518,1.8167
7519,1.813
7520,1.7813
7521,1.7653
7522,1.7504
7523,1.7357
7524,1.7479
7525,1.706
7526,1.7372
7527,1.714
7528,1.7035
7529,1.6854
7530,1.721
7531,1.7293
7532,1.7228
7533,1.7
7534,1.7014
7535,1.6881
7536,1.6698
7537,1.6121
7538,1.5996
7539,1.5678
7540,1.5328
7541,1.5444
7542,1.6112
7543,1.6099
7544,1.5994
7545,1.57
7546,1.5905
7547,1.5987
7548,1.5783
7549,1.5657
7550,1.558
7551,1.5298
7552,1.4993
7553,1.4781
7554,1.4803
7555,1.4962
7556,1.4991
7557,1.5089
7558,1.4768
7559,1.4816
7560,1.5133
7561,1.5318
7562,1.5436
7563,1.5452
7564,1.5386
7565,1.4896
7566,1.5008
7567,1.4893
7568,1.4739
7569,1.4591
7570,1.4898
7571,1.4817
7572,1.4832
7573,1.4934
7574,1.4906
7575,1.5341
7576,1.5277
7577,1.5405
7578,1.5327
7579,1.4886
7580,1.4704
7581,1.4679
7582,1.4703
7583,1.4538
7584,1.4405
7585,1.4346
7586,1.4489
7587,1.4561
7588,1.4665
7589,1.5128
7590,1.5153
7591,1.5159
7592,1.4779
7593,1.4499
7594,1.4494
7595,1.4518
7596,1.4779
7597,1.4482
7598,1.394
7599,1.3732
7600,1.374
7601,1.3666
7602,1.3926
7603,1.4153
7604,1.4282
7605,1.4308
7606,1.4414
7607,1.4169
7608,1.4358
7609,1.4546
7610,1.462
7611,1.4725
7612,1.4902
7613,1.4676
7614,1.4369
7615,1.426
7616,1.4454
7617,1.4257
7618,1.4264
7619,1.4178
7620,1.4304
7621,1.4313
7622,1.454
7623,1.4422
7624,1.4251
7625,1.4376
7626,1.4269
7627,1.402
7628,1.4058
7629,1.4134
7630,1.4148
7631,1.4173
7632,1.3809
7633,1.3919
7634,1.3829
7635,1.3856
7636,1.4018
7637,1.4143
7638,1.4072
7639,1.4026
7640,1.4615
7641,1.4478
7642,1.4526
7643,1.4761
7644,1.4623
7645,1.4525
7646,1.4348
7647,1.4217
7648,1.4358
7649,1.4411
7650,1.4766
7651,1.4823
7652,1.4816
7653,1.4772
7654,1.4661
7655,1.4676
7656,1.4905
7657,1.4986
7658,1.491
7659,1.48
7660,1.4532
7661,1.4618
7662,1.4534
7663,1.461
7664,1.4717
7665,1.4661
7666,1.4662
7667,1.477
7668,1.4822
7669,1.486
7670,1.5071
7671,1.5044
7672,1.503
7673,1.505
7674,1.5094
7675,1.5252
7676,1.5145
7677,1.5133
7678,1.5246
7679,1.5292
7680,1.5487
7681,1.5625
7682,1.5691
7683,1.5861
7684,1.5924
7685,1.602
7686,1.5956
7687,1.6109
7688,1.6412
7689,1.655
7690,1.6362
7691,1.618
7692,1.6001
7693,1.5978
7694,1.626
7695,1.6353
7696,1.6506
7697,1.6441
7698,1.6323
7699,1.6432
7700,1.6281
7701,1.6343
7702,1.6429
7703,1.6385
7704,1.6303
7705,1.6483
7706,1.6281
7707,1.6504
7708,1.6534
7709,1.645
7710,1.6455
7711,1.6351
7712,1.6324
7713,1.6184
7714,1.6175
7715,1.6079
7716,1.6217
7717,1.6186
7718,1.6094
7719,1.6266
7720,1.6408
7721,1.6419
7722,1.6314
7723,1.6462
7724,1.6442
7725,1.6415
7726,1.6507
7727,1.6397
7728,1.6477
7729,1.6448
7730,1.6397
7731,1.6483
7732,1.6569
7733,1.6915
7734,1.6879
7735,1.6929
7736,1.6784
7737,1.6666
7738,1.6527
7739,1.6483
7740,1.6526
7741,1.6584
7742,1.652
7743,1.6298
7744,1.6512
7745,1.6484
7746,1.6473
7747,1.6501
7748,1.6404
7749,1.6366
7750,1.6206
7751,1.6165
7752,1.6301
7753,1.6207
7754,1.6227
7755,1.6321
7756,1.6334
7757,1.6368
7758,1.6559
7759,1.6557
7760,1.6664
7761,1.6692
7762,1.6602
7763,1.6434
7764,1.6504
7765,1.6542
7766,1.6297
7767,1.6185
7768,1.6375
7769,1.642
7770,1.6064
7771,1.5942
7772,1.5887
7773,1.5926
7774,1.5985
7775,1.5975
7776,1.5881
7777,1.5929
7778,1.5915
7779,1.5894
7780,1.6083
7781,1.5913
7782,1.577
7783,1.5833
7784,1.5931
7785,1.6244
7786,1.632
7787,1.6361
7788,1.6412
7789,1.6577
7790,1.653
7791,1.631
7792,1.6325
7793,1.631
7794,1.6342
7795,1.6522
7796,1.6441
7797,1.634
7798,1.6351
7799,1.6538
7800,1.6543
7801,1.6555
7802,1.6697
7803,1.6673
7804,1.6533
7805,1.6496
7806,1.6622
7807,1.6718
7808,1.6741
7809,1.671
7810,1.657
7811,1.6463
7812,1.656
7813,1.652
7814,1.6591
7815,1.6447
7816,1.6445
7817,1.6366
7818,1.6582
7819,1.6616
7820,1.6539
7821,1.6495
7822,1.639
7823,1.6265
7824,1.6178
7825,1.6212
7826,1.6194
7827,1.6221
7828,1.6222
7829,1.6355
7830,1.6089
7831,1.6045
7832,1.6031
7833,1.5893
7834,1.5931
7835,1.5896
7836,1.593
7837,1.5969
7838,1.6111
7839,1.6084
7840,1.5995
7841,1.5963
7842,1.5895
7843,1.592
7844,1.6133
7845,1.6151
7846,1.6223
7847,1.627
7848,1.6209
7849,1.6288
7850,1.6314
7851,1.622
7852,1.6125
7853,1.6078
7854,1.6157
7855,1.61
7856,1.6139
7857,1.6086
7858,1.5972
7859,1.5856
7860,1.5922
7861,1.5893
7862,1.574
7863,1.5609
7864,1.56
7865,1.5567
7866,1.5556
7867,1.558
7868,1.5608
7869,1.5616
7870,1.5643
7871,1.569
7872,1.561
7873,1.5387
7874,1.546
7875,1.5416
7876,1.5418
7877,1.5221
7878,1.5191
7879,1.4902
7880,1.489
7881,1.5028
7882,1.5016
7883,1.507
7884,1.504
7885,1.4953
7886,1.4941
7887,1.5012
7888,1.515
7889,1.5017
7890,1.5163
7891,1.5266
7892,1.5219
7893,1.4993
7894,1.5046
7895,1.5041
7896,1.4891
7897,1.4864
7898,1.4882
7899,1.4958
7900,1.5084
7901,1.5143
7902,1.5257
7903,1.5182
7904,1.5181
7905,1.5221
7906,1.5333
7907,1.5365
7908,1.534
7909,1.5438
7910,1.5477
7911,1.5384
7912,1.5278
7913,1.5334
7914,1.5381
7915,1.5359
7916,1.5324
7917,1.5435
7918,1.5317
7919,1.5177
7920,1.5253
7921,1.5291
7922,1.5098
7923,1.5109
7924,1.4972
7925,1.4684
7926,1.4977
7927,1.4856
7928,1.4851
7929,1.4672
7930,1.4556
7931,1.4433
7932,1.4435
7933,1.4375
7934,1.4315
7935,1.4456
7936,1.4428
7937,1.4372
7938,1.4456
7939,1.45
7940,1.4481
7941,1.4719
7942,1.4591
7943,1.4634
7944,1.4566
7945,1.4509
7946,1.4383
7947,1.4604
7948,1.4671
7949,1.4561
7950,1.4791
7951,1.4822
7952,1.4842
7953,1.4796
7954,1.4803
7955,1.4818
7956,1.4799
7957,1.4902
7958,1.4967
7959,1.4978
7960,1.5106
7961,1.506
7962,1.4959
7963,1.5107
7964,1.5184
7965,1.5103
7966,1.5213
7967,1.519
7968,1.5143
7969,1.5094
7970,1.506
7971,1.5153
7972,1.5246
7973,1.5351
7974,1.5316
7975,1.5187
7976,1.5212
7977,1.5185
7978,1.5233
7979,1.5371
7980,1.5438
7981,1.5517
7982,1.5583
7983,1.5571
7984,1.5625
7985,1.5857
7986,1.5914
7987,1.5839
7988,1.579
7989,1.5932
7990,1.5914
7991,1.5697
7992,1.5623
7993,1.5554
7994,1.5554
7995,1.5641
7996,1.5543
7997,1.5555
7998,1.5596
7999,1.5473
8000,1.5469
8001,1.5418
8002,1.5393
8003,1.5549
8004,1.544
8005,1.5332
8006,1.5427
8007,1.5366
8008,1.5402
8009,1.5372
8010,1.5268
8011,1.545
8012,1.5438
8013,1.5346
8014,1.5395
8015,1.5458
8016,1.5593
8017,1.5592
8018,1.5592
8019,1.5529
8020,1.5494
8021,1.5618
8022,1.5676
8023,1.577
8024,1.5789
8025,1.5763
8026,1.576
8027,1.5712
8028,1.5768
8029,1.5796
8030,1.5876
8031,1.5844
8032,1.5893
8033,1.5882
8034,1.5857
8035,1.5736
8036,1.5789
8037,1.5968
8038,1.5957
8039,1.5848
8040,1.5674
8041,1.5801
8042,1.5707
8043,1.5602
8044,1.5649
8045,1.5792
8046,1.571
8047,1.5872
8048,1.592
8049,1.5984
8050,1.5946
8051,1.6015
8052,1.6212
8053,1.6144
8054,1.6075
8055,1.6055
8056,1.5965
8057,1.609
8058,1.6083
8059,1.6
8060,1.5845
8061,1.5852
8062,1.5923
8063,1.5885
8064,1.5882
8065,1.5817
8066,1.5731
8067,1.5716
8068,1.5568
8069,1.5488
8070,1.5537
8071,1.5531
8072,1.5509
8073,1.5664
8074,1.5631
8075,1.5759
8076,1.5722
8077,1.5671
8078,1.5737
8079,1.5799
8080,1.5721
8081,1.5561
8082,1.5531
8083,1.5403
8084,1.5427
8085,1.5407
8086,1.5331
8087,1.5339
8088,1.5381
8089,1.5364
8090,1.5327
8091,1.5589
8092,1.5525
8093,1.5395
8094,1.5405
8095,1.5492
8096,1.5489
8097,1.5483
8098,1.5608
8099,1.5765
8100,1.5789
8101,1.5814
8102,1.5889
8103,1.5892
8104,1.5747
8105,1.5897
8106,1.5913
8107,1.5749
8108,1.5801
8109,1.585
8110,1.5761
8111,1.5929
8112,1.6057
8113,1.6084
8114,1.6041
8115,1.5953
8116,1.6001
8117,1.5991
8118,1.6006
8119,1.5974
8120,1.5895
8121,1.589
8122,1.605
8123,1.5934
8124,1.6041
8125,1.6089
8126,1.6098
8127,1.6059
8128,1.6114
8129,1.5993
8130,1.5962
8131,1.6149
8132,1.6192
8133,1.6209
8134,1.6161
8135,1.6147
8136,1.6114
8137,1.6039
8138,1.6095
8139,1.5933
8140,1.5911
8141,1.6074
8142,1.5965
8143,1.5934
8144,1.6041
8145,1.6087
8146,1.6172
8147,1.6272
8148,1.6134
8149,1.6057
8150,1.5981
8151,1.5909
8152,1.5871
8153,1.5952
8154,1.5913
8155,1.591
8156,1.6015
8157,1.6145
8158,1.6191
8159,1.6187
8160,1.6264
8161,1.6296
8162,1.6159
8163,1.6177
8164,1.6253
8165,1.6199
8166,1.6097
8167,1.6208
8168,1.6303
8169,1.6467
8170,1.6344
8171,1.641
8172,1.6539
8173,1.639
8174,1.644
8175,1.6313
8176,1.6319
8177,1.6199
8178,1.6249
8179,1.6351
8180,1.6165
8181,1.6108
8182,1.6134
8183,1.611
8184,1.6046
8185,1.6066
8186,1.6098
8187,1.6028
8188,1.609
8189,1.6179
8190,1.6253
8191,1.6367
8192,1.6364
8193,1.6306
8194,1.6241
8195,1.6268
8196,1.6258
8197,1.6358
8198,1.6279
8199,1.6276
8200,1.6141
8201,1.6219
8202,1.6298
8203,1.617
8204,1.6044
8205,1.6083
8206,1.613
8207,1.6135
8208,1.6057
8209,1.5904
8210,1.5898
8211,1.5933
8212,1.5932
8213,1.5948
8214,1.5978
8215,1.5969
8216,1.5988
8217,1.6022
8218,1.5905
8219,1.5909
8220,1.5979
8221,1.5821
8222,1.5848
8223,1.6018
8224,1.6052
8225,1.6052
8226,1.5962
8227,1.6104
8228,1.6075
8229,1.6226
8230,1.6238
8231,1.6214
8232,1.6316
8233,1.6272
8234,1.6268
8235,1.635
8236,1.6195
8237,1.6236
8238,1.6348
8239,1.6256
8240,1.6327
8241,1.6255
8242,1.6167
8243,1.6094
8244,1.617
8245,1.6217
8246,1.6341
8247,1.6355
8248,1.6497
8249,1.6404
8250,1.6504
8251,1.6375
8252,1.6429
8253,1.6333
8254,1.6193
8255,1.6159
8256,1.6209
8257,1.6212
8258,1.6091
8259,1.6139
8260,1.6044
8261,1.5945
8262,1.5886
8263,1.6005
8264,1.5839
8265,1.5756
8266,1.5746
8267,1.5688
8268,1.5752
8269,1.5744
8270,1.5588
8271,1.5671
8272,1.5555
8273,1.5297
8274,1.5392
8275,1.5504
8276,1.5651
8277,1.5605
8278,1.5636
8279,1.5533
8280,1.5432
8281,1.5367
8282,1.5387
8283,1.5342
8284,1.557
8285,1.5628
8286,1.5575
8287,1.5728
8288,1.568
8289,1.5743
8290,1.5721
8291,1.5586
8292,1.5776
8293,1.5633
8294,1.5891
8295,1.5893
8296,1.5904
8297,1.5848
8298,1.5995
8299,1.6081
8300,1.6075
8301,1.5882
8302,1.5903
8303,1.5893
8304,1.596
8305,1.5959
8306,1.6011
8307,1.5881
8308,1.5815
8309,1.6011
8310,1.5837
8311,1.5756
8312,1.5735
8313,1.5735
8314,1.5731
8315,1.5567
8316,1.5586
8317,1.5459
8318,1.5458
8319,1.5439
8320,1.5501
8321,1.5565
8322,1.5674
8323,1.5625
8324,1.5575
8325,1.5653
8326,1.555
8327,1.5621
8328,1.5577
8329,1.5566
8330,1.5563
8331,1.5482
8332,1.5362
8333,1.5424
8334,1.5478
8335,1.5479
8336,1.5641
8337,1.5606
8338,1.5631
8339,1.562
8340,1.5415
8341,1.534
8342,1.5407
8343,1.5577
8344,1.5548
8345,1.5421
8346,1.5351
8347,1.5389
8348,1.5429
8349,1.5299
8350,1.5264
8351,1.523
8352,1.5273
8353,1.5299
8354,1.535
8355,1.5418
8356,1.5469
8357,1.5535
8358,1.5529
8359,1.553
8360,1.5641
8361,1.5614
8362,1.5626
8363,1.5724
8364,1.5801
8365,1.576
8366,1.5739
8367,1.5737
8368,1.5815
8369,1.5771
8370,1.5786
8371,1.5696
8372,1.5736
8373,1.5615
8374,1.5637
8375,1.5692
8376,1.5756
8377,1.5809
8378,1.5761
8379,1.5616
8380,1.5653
8381,1.5808
8382,1.5793
8383,1.5792
8384,1.5929
8385,1.5905
8386,1.5813
8387,1.5829
8388,1.5695
8389,1.5662
8390,1.5768
8391,1.5646
8392,1.5573
8393,1.5692
8394,1.5644
8395,1.5623
8396,1.5799
8397,1.5847
8398,1.5813
8399,1.5803
8400,1.5764
8401,1.5819
8402,1.5892
8403,1.5925
8404,1.5809
8405,1.5869
8406,1.5941
8407,1.5975
8408,1.5935
8409,1.5833
8410,1.5792
8411,1.5801
8412,1.5864
8413,1.5908
8414,1.5842
8415,1.5799
8416,1.588
8417,1.5982
8418,1.6012
8419,1.6065
8420,1.6046
8421,1.61
8422,1.6065
8423,1.6141
8424,1.6192
8425,1.619
8426,1.6173
8427,1.6159
8428,1.6156
8429,1.6114
8430,1.6099
8431,1.6058
8432,1.6115
8433,1.6056
8434,1.6062
8435,1.6001
8436,1.5883
8437,1.578
8438,1.5776
8439,1.5773
8440,1.5769
8441,1.5694
8442,1.5658
8443,1.5614
8444,1.5684
8445,1.5652
8446,1.5512
8447,1.5371
8448,1.5324
8449,1.5441
8450,1.5551
8451,1.5396
8452,1.5485
8453,1.5523
8454,1.556
8455,1.5531
8456,1.5632
8457,1.5659
8458,1.5701
8459,1.5719
8460,1.5645
8461,1.554
8462,1.5548
8463,1.5584
8464,1.554
8465,1.5493
8466,1.567
8467,1.5676
8468,1.5666
8469,1.5563
8470,1.5508
8471,1.5499
8472,1.5513
8473,1.5486
8474,1.555
8475,1.5397
8476,1.5538
8477,1.5606
8478,1.5557
8479,1.5619
8480,1.5699
8481,1.5629
8482,1.5511
8483,1.5524
8484,1.5473
8485,1.5695
8486,1.5711
8487,1.5693
8488,1.5673
8489,1.5591
8490,1.5516
8491,1.5599
8492,1.5612
8493,1.5644
8494,1.5647
8495,1.5623
8496,1.5677
8497,1.5685
8498,1.5668
8499,1.5681
8500,1.5728
8501,1.5664
8502,1.5692
8503,1.5771
8504,1.5791
8505,1.5872
8506,1.5805
8507,1.5823
8508,1.5821
8509,1.5804
8510,1.5871
8511,1.5888
8512,1.5873
8513,1.5902
8514,1.5924
8515,1.6012
8516,1.5992
8517,1.604
8518,1.6072
8519,1.6089
8520,1.6211
8521,1.6231
8522,1.6232
8523,1.6201
8524,1.618
8525,1.6231
8526,1.6171
8527,1.6233
8528,1.6125
8529,1.6169
8530,1.6132
8531,1.6132
8532,1.6121
8533,1.6055
8534,1.6148
8535,1.6175
8536,1.6011
8537,1.5983
8538,1.6
8539,1.6017
8540,1.6064
8541,1.603
8542,1.6077
8543,1.6143
8544,1.6113
8545,1.6001
8546,1.6013
8547,1.5921
8548,1.6011
8549,1.6121
8550,1.6077
8551,1.6009
8552,1.6066
8553,1.6093
8554,1.6122
8555,1.602
8556,1.5957
8557,1.5967
8558,1.5972
8559,1.5956
8560,1.5898
8561,1.5856
8562,1.5882
8563,1.5832
8564,1.5864
8565,1.5837
8566,1.5903
8567,1.59
8568,1.5916
8569,1.5929
8570,1.5993
8571,1.6007
8572,1.6012
8573,1.5968
8574,1.6018
8575,1.6007
8576,1.6074
8577,1.6088
8578,1.6075
8579,1.6062
8580,1.6008
8581,1.6058
8582,1.6086
8583,1.61
8584,1.6118
8585,1.6102
8586,1.6179
8587,1.6231
8588,1.6253
8589,1.6242
8590,1.6166
8591,1.6159
8592,1.611
8593,1.6138
8594,1.6148
8595,1.6262
8596,1.6135
8597,1.601
8598,1.6058
8599,1.6014
8600,1.5986
8601,1.6082
8602,1.61
8603,1.6042
8604,1.6064
8605,1.5969
8606,1.5943
8607,1.5837
8608,1.5808
8609,1.584
8610,1.5817
8611,1.5759
8612,1.5782
8613,1.5687
8614,1.5725
8615,1.5765
8616,1.5829
8617,1.5718
8618,1.5713
8619,1.5647
8620,1.563
8621,1.568
8622,1.5814
8623,1.5641
8624,1.5638
8625,1.552
8626,1.5503
8627,1.5499
8628,1.5455
8629,1.542
8630,1.5283
8631,1.524
8632,1.5248
8633,1.5089
8634,1.5112
8635,1.5124
8636,1.5168
8637,1.4999
8638,1.5058
8639,1.5105
8640,1.5042
8641,1.5034
8642,1.4909
8643,1.4884
8644,1.4874
8645,1.4911
8646,1.5037
8647,1.5119
8648,1.5096
8649,1.5106
8650,1.5121
8651,1.5167
8652,1.5227
8653,1.517
8654,1.5142
8655,1.51
8656,1.5168
8657,1.5115
8658,1.5122
8659,1.5164
8660,1.5336
8661,1.5265
8662,1.5278
8663,1.5307
8664,1.5375
8665,1.535
8666,1.5294
8667,1.5273
8668,1.5217
8669,1.5274
8670,1.5242
8671,1.5229
8672,1.5269
8673,1.5251
8674,1.5422
8675,1.5473
8676,1.5473
8677,1.5542
8678,1.553
8679,1.549
8680,1.5547
8681,1.5447
8682,1.5541
8683,1.5472
8684,1.533
8685,1.532
8686,1.5233
8687,1.5202
8688,1.5285
8689,1.5169
8690,1.52
8691,1.5118
8692,1.5024
8693,1.5045
8694,1.5118
8695,1.5014
8696,1.5094
8697,1.5195
8698,1.5137
8699,1.5266
8700,1.5267
8701,1.5367
8702,1.5497
8703,1.551
8704,1.5498
8705,1.5569
8706,1.5658
8707,1.5651
8708,1.5647
8709,1.5683
8710,1.5576
8711,1.5628
8712,1.5433
8713,1.5357
8714,1.5369
8715,1.5372
8716,1.531
8717,1.5174
8718,1.5137
8719,1.5194
8720,1.5139
8721,1.5228
8722,1.5039
8723,1.4858
8724,1.4914
8725,1.4808
8726,1.4922
8727,1.5086
8728,1.5088
8729,1.5076
8730,1.5098
8731,1.5146
8732,1.5175
8733,1.5233
8734,1.5341
8735,1.5338
8736,1.533
8737,1.529
8738,1.5346
8739,1.5323
8740,1.5235
8741,1.5141
8742,1.5135
8743,1.5244
8744,1.5298
8745,1.5353
8746,1.5486
8747,1.5522
8748,1.5497
8749,1.5449
8750,1.5429
8751,1.5502
8752,1.552
8753,1.5578
8754,1.5633
8755,1.5645
8756,1.5652
8757,1.5539
8758,1.5557
8759,1.5506
8760,1.5504
8761,1.5462
8762,1.5437
8763,1.5531
8764,1.5497
8765,1.5595
8766,1.5555
8767,1.5592
8768,1.5682
8769,1.5682
8770,1.5776
8771,1.5789
8772,1.5828
8773,1.5896
8774,1.5863
8775,1.5928
8776,1.6023
8777,1.5958
8778,1.599
8779,1.5944
8780,1.6029
8781,1.5964
8782,1.6081
8783,1.6153
8784,1.6163
8785,1.6186
8786,1.6127
8787,1.6029
8788,1.6036
8789,1.6067
8790,1.5891
8791,1.591
8792,1.5902
8793,1.5972
8794,1.5921
8795,1.5883
8796,1.61
8797,1.614
8798,1.6112
8799,1.6165
8800,1.6121
8801,1.6119
8802,1.612
8803,1.6084
8804,1.6012
8805,1.6031
8806,1.6021
8807,1.5876
8808,1.5906
8809,1.5993
8810,1.603
8811,1.5998
8812,1.5945
8813,1.5922
8814,1.5878
8815,1.594
8816,1.6043
8817,1.6042
8818,1.6063
8819,1.6054
8820,1.6122
8821,1.6097
8822,1.6135
8823,1.6104
8824,1.6132
8825,1.6227
8826,1.6295
8827,1.6332
8828,1.6316
8829,1.6362
8830,1.6292
8831,1.6269
8832,1.6302
8833,1.6341
8834,1.638
8835,1.6321
8836,1.6278
8837,1.6229
8838,1.6253
8839,1.6195
8840,1.6341
8841,1.6318
8842,1.6307
8843,1.6306
8844,1.6307
8845,1.6439
8846,1.647
8847,1.6472
8848,1.6382
8849,1.639
8850,1.6361
8851,1.6347
8852,1.6418
8853,1.6412
8854,1.6434
8855,1.6334
8856,1.641
8857,1.6301
8858,1.6295
8859,1.6393
8860,1.6369
8861,1.6412
8862,1.6526
8863,1.6576
8864,1.645
8865,1.6522
8866,1.6532
8867,1.6501
8868,1.6447
8869,1.6384
8870,1.6281
8871,1.6245
8872,1.6255
8873,1.6275
8874,1.6343
8875,1.6347
8876,1.6433
8877,1.6528
8878,1.658
8879,1.6674
8880,1.6654
8881,1.6644
8882,1.6659
8883,1.6604
8884,1.6631
8885,1.6577
8886,1.6627
8887,1.6586
8888,1.6617
8889,1.6703
8890,1.6663
8891,1.6619
8892,1.6675
8893,1.6663
8894,1.6668
8895,1.6578
8896,1.6573
8897,1.6552
8898,1.6623
8899,1.6577
8900,1.6591
8901,1.6522
8902,1.6575
8903,1.6456
8904,1.6441
8905,1.6436
8906,1.6452
8907,1.6511
8908,1.6556
8909,1.658
8910,1.6617
8911,1.658
8912,1.6578
8913,1.653
8914,1.6533
8915,1.6555
8916,1.6693
8917,1.6691
8918,1.6718
8919,1.6664
8920,1.6679
8921,1.6673
8922,1.6731
8923,1.6745
8924,1.676
8925,1.6716
8926,1.6737
8927,1.6749
8928,1.6744
8929,1.678
8930,1.682
8931,1.6831
8932,1.6807
8933,1.6923
8934,1.6895
8935,1.6883
8936,1.677
8937,1.6798
8938,1.6767
8939,1.6712
8940,1.6732
8941,1.6765
8942,1.6763
8943,1.6782
8944,1.681
8945,1.679
8946,1.6775
8947,1.6736
8948,1.664
8949,1.6651
8950,1.6708
8951,1.669
8952,1.667
8953,1.6686
8954,1.6724
8955,1.6723
8956,1.6727
8957,1.6692
8958,1.672
8959,1.6772
8960,1.6871
8961,1.6895
8962,1.6879
8963,1.6853
8964,1.6965
8965,1.6926
8966,1.692
8967,1.6883
8968,1.6894
8969,1.6919
8970,1.6929
8971,1.7008
8972,1.7046
8973,1.7074
8974,1.7051
8975,1.7056
8976,1.7038
8977,1.7032
8978,1.7049
8979,1.7021
8980,1.7013
8981,1.7002
8982,1.705
8983,1.7051
8984,1.7007
8985,1.698
8986,1.698
8987,1.697
8988,1.6954
8989,1.6886
8990,1.6888
8991,1.6913
8992,1.6861
8993,1.682
8994,1.68
8995,1.6755
8996,1.6757
8997,1.6786
8998,1.6747
8999,1.6758
9000,1.6714
9001,1.6705
9002,1.6719
9003,1.6617
9004,1.6609
9005,1.6609
9006,1.6644
9007,1.6542
9008,1.6566
9009,1.652
9010,1.6493
9011,1.6502
9012,1.651
9013,1.6508
9014,1.6536
9015,1.6543
9016,1.6436
9017,1.6379
9018,1.6327
9019,1.6252
9020,1.6098
9021,1.6043
9022,1.6083
9023,1.6169
9024,1.6164
9025,1.6168
9026,1.6152
9027,1.6254
9028,1.6319
9029,1.6238
9030,1.6253
9031,1.6287
9032,1.6275
</plot-data>
</body>
</html>
/* SVG CSS */
.radian svg {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Trying to get SVG to act like a greedy block in all browsers */
display: block;
width:100%;
height:100%;
}
.radian svg .no-data text { font-size: 24px; font-weight: bold; }
.radian .background {
fill: white;
fill-opacity: 0;
/*
pointer-events: none;
*/
}
div.radian { position: relative; }
div.radian div.radian { position: absolute; }
div.radian-ui {
background-color: transparent;
position: absolute;
top: 0px;
left: 0px; }
div.radian-axis-switch { position: absolute; white-space: nowrap; }
div.radian-stroke-switch { position: absolute; white-space: nowrap; }
div.radian-histogram-switch { position: absolute; white-space: nowrap; }
div.radian-legend-switch { position: absolute; white-space: nowrap; }
div.radian-legend-switch input {
position: absolute;
display: block;
margin: 0px;
}
/* Axes */
.radian .axis path {
fill: none;
stroke: #000;
stroke-opacity: .75;
shape-rendering: crispEdges;
}
.radian .axis line {
fill: none;
stroke: #000;
stroke-opacity: .25;
shape-rendering: crispEdges;
}
.radian .axis path.domain { stroke-opacity: .75; }
.radian .axis line.zero { stroke-opacity: .75; }
.radian .axis .axisMaxMin text { font-weight: bold; }
/* Brush */
.radian .brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.tab-content.radian-tabs { overflow: visible; }
/********************
* HTML CSS
*/
/* .chartWrap { */
/* margin: 0; */
/* padding: 0; */
/* overflow: hidden; */
/* } */
/********************
* TOOLTIP CSS
*/
/* .nvtooltip { */
/* position: absolute; */
/* background-color: rgba(255,255,255,1); */
/* padding: 10px; */
/* border: 1px solid #ddd; */
/* z-index: 10000; */
/* font-family: Arial; */
/* font-size: 13px; */
/* transition: opacity 500ms linear; */
/* -moz-transition: opacity 500ms linear; */
/* -webkit-transition: opacity 500ms linear; */
/* transition-delay: 500ms; */
/* -moz-transition-delay: 500ms; */
/* -webkit-transition-delay: 500ms; */
/* -moz-box-shadow: 4px 4px 8px rgba(0,0,0,.5); */
/* -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,.5); */
/* box-shadow: 4px 4px 8px rgba(0,0,0,.5); */
/* -moz-border-radius: 10px; */
/* border-radius: 10px; */
/* pointer-events: none; */
/* -webkit-touch-callout: none; */
/* -webkit-user-select: none; */
/* -khtml-user-select: none; */
/* -moz-user-select: none; */
/* -ms-user-select: none; */
/* user-select: none; */
/* } */
/* .nvtooltip h3 { */
/* margin: 0; */
/* padding: 0; */
/* text-align: center; */
/* } */
/* .nvtooltip p { */
/* margin: 0; */
/* padding: 0; */
/* text-align: center; */
/* } */
/* .nvtooltip span { */
/* display: inline-block; */
/* margin: 2px 0; */
/* } */
/* .nvtooltip-pending-removal { */
/* position: absolute; */
/* pointer-events: none; */
/* } */
/**********
* Legend
*/
/* .radian .nv-legend .nv-series { */
/* cursor: pointer; */
/* } */
/* .radian .nv-legend .disabled circle { */
/* fill-opacity: 0; */
/* } */
/**********
* Brush
*/
/* .nv-brush .resize path { */
/* fill: #eee; */
/* stroke: #666; */
/* } */
/**********
* Bars
*/
/* .radian .nv-bars .negative rect { */
/* zfill: brown; */
/* } */
/* .radian .nv-bars rect { */
/* zfill: steelblue; */
/* fill-opacity: .75; */
/* transition: fill-opacity 250ms linear; */
/* -moz-transition: fill-opacity 250ms linear; */
/* -webkit-transition: fill-opacity 250ms linear; */
/* } */
/* .radian .nv-bars rect:hover { */
/* fill-opacity: 1; */
/* } */
/* .radian .nv-bars .hover rect { */
/* fill: lightblue; */
/* } */
/* .radian .nv-bars text { */
/* fill: rgba(0,0,0,0); */
/* } */
/* .radian .nv-bars .hover text { */
/* fill: rgba(0,0,0,1); */
/* } */
/**********
* Bars
*/
/* .radian .nv-multibar .nv-groups rect, */
/* .radian .nv-multibarHorizontal .nv-groups rect, */
/* .radian .nv-discretebar .nv-groups rect { */
/* stroke-opacity: 0; */
/* transition: fill-opacity 250ms linear; */
/* -moz-transition: fill-opacity 250ms linear; */
/* -webkit-transition: fill-opacity 250ms linear; */
/* } */
/* .radian .nv-multibar .nv-groups rect:hover, */
/* .radian .nv-multibarHorizontal .nv-groups rect:hover, */
/* .radian .nv-discretebar .nv-groups rect:hover { */
/* fill-opacity: 1; */
/* } */
/* .radian .nv-discretebar .nv-groups text, */
/* .radian .nv-multibarHorizontal .nv-groups text { */
/* font-weight: bold; */
/* fill: rgba(0,0,0,1); */
/* stroke: rgba(0,0,0,0); */
/* } */
/***********
* Pie Chart
*/
/* .radian.nv-pie path { */
/* stroke-opacity: 0; */
/* transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* } */
/* .radian.nv-pie .nv-slice text { */
/* stroke: #000; */
/* stroke-width: 0; */
/* } */
/* .radian.nv-pie path { */
/* stroke: #fff; */
/* stroke-width: 1px; */
/* stroke-opacity: 1; */
/* } */
/* .radian.nv-pie .hover path { */
/* fill-opacity: .7; */
/* /\* */
/* stroke-width: 6px; */
/* stroke-opacity: 1; */
/* *\/ */
/* } */
/* .radian.nv-pie .nv-label rect { */
/* fill-opacity: 0; */
/* stroke-opacity: 0; */
/* } */
/**********
* Lines
*/
/* .radian .nv-groups path.nv-line { */
/* fill: none; */
/* stroke-width: 2.5px; */
/* /\* */
/* stroke-linecap: round; */
/* shape-rendering: geometricPrecision; */
/* transition: stroke-width 250ms linear; */
/* -moz-transition: stroke-width 250ms linear; */
/* -webkit-transition: stroke-width 250ms linear; */
/* transition-delay: 250ms */
/* -moz-transition-delay: 250ms; */
/* -webkit-transition-delay: 250ms; */
/* *\/ */
/* } */
/* .radian .nv-groups path.nv-line-multiple { */
/* fill: none; */
/* stroke-width: 1.5px; */
/* } */
/* .radian .nv-groups path.nv-line-vary { */
/* fill: none; */
/* stroke-width: 1.5px; */
/* } */
/* .radian .nv-groups path.nv-line-vary-multiple { */
/* fill: none; */
/* stroke-width: 1.5px; */
/* } */
/* .radian .nv-groups path.nv-area { */
/* stroke: none; */
/* /\* */
/* stroke-linecap: round; */
/* shape-rendering: geometricPrecision; */
/* stroke-width: 2.5px; */
/* transition: stroke-width 250ms linear; */
/* -moz-transition: stroke-width 250ms linear; */
/* -webkit-transition: stroke-width 250ms linear; */
/* transition-delay: 250ms */
/* -moz-transition-delay: 250ms; */
/* -webkit-transition-delay: 250ms; */
/* *\/ */
/* } */
/* .radian .nv-line.hover path { */
/* stroke-width: 6px; */
/* } */
/* /\* */
/* .radian.scatter .groups .point { */
/* fill-opacity: 0.1; */
/* stroke-opacity: 0.1; */
/* } */
/* *\/ */
/* .radian.nv-line .radian.nv-scatter .nv-groups .nv-point { */
/* fill-opacity: 0; */
/* stroke-opacity: 0; */
/* } */
/* .radian.nv-scatter.nv-single-point .nv-groups .nv-point { */
/* fill-opacity: .5 !important; */
/* stroke-opacity: .5 !important; */
/* } */
/* .radian .nv-groups .nv-point { */
/* transition: stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; */
/* } */
/* .radian.nv-scatter .nv-groups .nv-point.hover, */
/* .radian .nv-groups .nv-point.hover { */
/* stroke-width: 20px; */
/* fill-opacity: .5 !important; */
/* stroke-opacity: .5 !important; */
/* } */
/* .radian .nv-point-paths path { */
/* stroke: #aaa; */
/* stroke-opacity: 0; */
/* fill: #eee; */
/* fill-opacity: 0; */
/* } */
/* .radian .nv-indexLine { */
/* cursor: ew-resize; */
/* } */
/**********
* Distribution
*/
/* .radian .nv-distribution { */
/* pointer-events: none; */
/* } */
/**********
* Scatter
*/
/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
.radian .nv-groups .nv-point {
pointer-events: none;
}
*/
/* .radian .nv-groups .nv-point.hover { */
/* stroke-width: 20px; */
/* stroke-opacity: .5; */
/* } */
/* .radian .nv-scatter .nv-point.hover { */
/* fill-opacity: 1; */
/* } */
/* /\* */
/* .nv-group.hover .nv-point { */
/* fill-opacity: 1; */
/* } */
/* *\/ */
/**********
* Stacked Area
*/
/* .radian.nv-stackedarea path.nv-area { */
/* fill-opacity: .7; */
/* /\* */
/* stroke-opacity: .65; */
/* fill-opacity: 1; */
/* *\/ */
/* stroke-opacity: 0; */
/* transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; */
/* -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; */
/* -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; */
/* /\* */
/* transition-delay: 500ms; */
/* -moz-transition-delay: 500ms; */
/* -webkit-transition-delay: 500ms; */
/* *\/ */
/* } */
/* .radian.nv-stackedarea path.nv-area.hover { */
/* fill-opacity: .9; */
/* /\* */
/* stroke-opacity: .85; */
/* *\/ */
/* } */
/* /\* */
/* .d3stackedarea .groups path { */
/* stroke-opacity: 0; */
/* } */
/* *\/ */
/* .radian.nv-stackedarea .nv-groups .nv-point { */
/* stroke-opacity: 0; */
/* fill-opacity: 0; */
/* } */
/* .radian.nv-stackedarea .nv-groups .nv-point.hover { */
/* stroke-width: 20px; */
/* stroke-opacity: .75; */
/* fill-opacity: 1; */
/* } */
/**********
* Line Plus Bar
*/
/* .radian.nv-linePlusBar .nv-bar rect { */
/* fill-opacity: .75; */
/* } */
/* .radian.nv-linePlusBar .nv-bar rect:hover { */
/* fill-opacity: 1; */
/* } */
/**********
* Bullet
*/
/* .radian.nv-bullet { font: 10px sans-serif; } */
/* .radian.nv-bullet .nv-measure { fill-opacity: .8; } */
/* .radian.nv-bullet .nv-measure:hover { fill-opacity: 1; } */
/* .radian.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } */
/* .radian.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } */
/* .radian.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } */
/* .radian.nv-bullet .nv-range.nv-s0 { fill: #eee; } */
/* .radian.nv-bullet .nv-range.nv-s1 { fill: #ddd; } */
/* .radian.nv-bullet .nv-range.nv-s2 { fill: #ccc; } */
/* .radian.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } */
/* .radian.nv-bullet .nv-subtitle { fill: #999; } */
/* .radian.nv-bullet .nv-range { */
/* fill: #999; */
/* fill-opacity: .4; */
/* } */
/* .radian.nv-bullet .nv-range:hover { */
/* fill-opacity: .7; */
/* } */
/**********
* Sparkline
*/
/* .radian.nv-sparkline path { */
/* fill: none; */
/* } */
/* .radian.nv-sparklineplus g.nv-hoverValue { */
/* pointer-events: none; */
/* } */
/* .radian.nv-sparklineplus .nv-hoverValue line { */
/* stroke: #333; */
/* stroke-width: 1.5px; */
/* } */
/* .radian.nv-sparklineplus, */
/* .radian.nv-sparklineplus g { */
/* pointer-events: all; */
/* } */
/* .radian .nv-hoverArea { */
/* fill-opacity: 0; */
/* stroke-opacity: 0; */
/* } */
/* .radian.nv-sparklineplus .nv-xValue, */
/* .radian.nv-sparklineplus .nv-yValue { */
/* /\* */
/* stroke: #666; */
/* *\/ */
/* stroke-width: 0; */
/* font-size: .9em; */
/* font-weight: normal; */
/* } */
/* .radian.nv-sparklineplus .nv-yValue { */
/* stroke: #f66; */
/* } */
/* .radian.nv-sparklineplus .nv-maxValue { */
/* stroke: #2ca02c; */
/* fill: #2ca02c; */
/* } */
/* .radian.nv-sparklineplus .nv-minValue { */
/* stroke: #d62728; */
/* fill: #d62728; */
/* } */
/* .radian.nv-sparklineplus .nv-currentValue { */
/* /\* */
/* stroke: #444; */
/* fill: #000; */
/* *\/ */
/* font-weight: bold; */
/* font-size: 1.1em; */
/* } */
/**********
* historical stock
*/
/* .radian.nv-ohlcBar .nv-ticks .nv-tick { */
/* stroke-width: 2px; */
/* } */
/* .radian.nv-ohlcBar .nv-ticks .nv-tick.hover { */
/* stroke-width: 4px; */
/* } */
/* .radian.nv-ohlcBar .nv-ticks .nv-tick.positive { */
/* stroke: #2ca02c; */
/* } */
/* .radian.nv-ohlcBar .nv-ticks .nv-tick.negative { */
/* stroke: #d62728; */
/* } */
/* .radian.nv-historicalStockChart .nv-axis .nv-axislabel { */
/* font-weight: bold; */
/* } */
/* .radian.nv-historicalStockChart .nv-dragTarget { */
/* fill-opacity: 0; */
/* stroke: none; */
/* cursor: move; */
/* } */
/* .radian .nv-brush .extent { */
/* /\* */
/* cursor: ew-resize !important; */
/* *\/ */
/* fill-opacity: 0 !important; */
/* } */
/* .radian .nv-brushBackground rect { */
/* stroke: #000; */
/* stroke-width: .4; */
/* fill: #fff; */
/* fill-opacity: .7; */
/* } */
/**********
* Indented Tree
*/
/**
* TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library
*/
/* .radian.nv-indentedtree .name { */
/* margin-left: 5px; */
/* } */
/* .radian.nv-indentedtree .clickable { */
/* color: #08C; */
/* cursor: pointer; */
/* } */
/* .radian.nv-indentedtree span.clickable:hover { */
/* color: #005580; */
/* text-decoration: underline; */
/* } */
/* .radian.nv-indentedtree .nv-childrenCount { */
/* display: inline-block; */
/* margin-left: 5px; */
/* } */
/* .radian.nv-indentedtree .nv-treeicon { */
/* cursor: pointer; */
/* /\* */
/* cursor: n-resize; */
/* *\/ */
/* } */
/* .radian.nv-indentedtree .nv-treeicon.nv-folded { */
/* cursor: pointer; */
/* /\* */
/* cursor: s-resize; */
/* *\/ */
/* } */
var radian = angular.module('radian', []);
// Process attributes for plot directives. All attributes, except for
// a small number of special cases (ID, CLASS, NG-*) are added as
// Angular scope variables, along with some extra information about
// the free variables and the original expression for the attribute.
// Changes to the attribute value are processed by re-evaluation using
// $observe and changes to free variables in the Radian expression are
// processed using a (slightly complicated) setup of scope.$watch
// listeners.
radian.factory('processAttrs', ['radianEval', function(radianEval) {
'use strict';
return function(scope, as) {
scope.$$radianVars = { };
Object.keys(as).forEach(function(a) {
// Skip the specials.
if (a == "id" || a == "class" || a.charAt(0) == "$" ||
a.search(/^ng[A-Z]/) != -1) return;
// Passing the true flag to radianEval gets us the free
// variables in the expression as well as the current expression
// value.
var val = radianEval(scope, as[a], true, true);
// Record the original expression and its free variables and set
// the value of the scope variable.
scope.$$radianVars[a] = { fvs: val[1], expr: as[a] };
scope[a] = val[0];
// Set up watchers for each of the free variables in the
// expression. When these watchers are triggered, they just
// re-evaluate the expression for the attribute using its
// original textual form. We keep track of the return values
// from the calls to scope.$watch so that we can cancel these
// watches later if the free variables change.
var entry = scope.$$radianVars[a];
entry.fvwatchers = { };
entry.fvs.forEach(function(v) {
entry.fvwatchers[v] = scope.$watch(v, function(n, o) {
scope[a] = radianEval(scope, entry.expr);
}, true);
});
// Observe the value of the attribute: if the value (i.e. the
// expression) changes, we pull in the new expression,
// re-evaluate and rearrange the free variable watchers.
as.$observe(a, function(v) {
entry.expr = v;
try {
var val = radianEval(scope, v, true);
scope[a] = val[0];
entry.fvs = val[1];
Object.keys(entry.fvwatchers).forEach(function(v) {
// The new free variables are already in entry.fvs. If
// this one isn't in there, deregister the watch and
// remove it.
if (entry.fvs.indexOf(v) == -1) {
entry.fvwatchers[v]();
delete entry.fvwatchers[v];
}
});
// Add watchers for any new free variables.
entry.fvs.forEach(function(v) {
if (!entry.fvwatchers[v])
entry.fvwatchers[v] = scope.$watch(v, function() {
scope[a] = radianEval(scope, entry.expr);
}, true);
});
} catch (e) {
console.log("Exception in radianEval watcher. Skipping...");
}});
});
};
}]);
// Deal with plot dimension attributes: explicit attribute values
// override CSS values. Do sensible things with width, height and
// aspect ratio. This is called either for individual plots, or for
// the outermost plot layout directive (<plot-row>, <plot-col> or
// <plot-grid>).
radian.factory('calcPlotDimensions', function() {
return function(scope, elm, as) {
var relative = false;
var h = 300, asp = 1.618, w = asp * h;
var aw = as.width, ah = as.height, aasp = as.aspect;
var pw = elm.parent().width(), ph = elm.parent().height();
scope.parentWidth = pw; scope.parentHeight = ph;
var cw = elm.width(), ch = elm.height();
var casp = elm.css('aspect') ? parseFloat(elm.css('aspect')) : null;
if (aw) {
var aws = aw.toString();
if (aws.charAt(aws.length - 1) == '%') {
relative = true;
aw = pw * Number(aws.slice(0, aws.length - 1)) / 100;
}
}
if (ah) {
var ahs = ah.toString();
if (ahs.charAt(ahs.length - 1) == '%') {
relative = true;
ah = ph * Number(ahs.slice(0, ahs.length - 1)) / 100;
}
}
if (aw && ah && aasp || ah && aw) { h = ah; w = aw; asp = w / h; }
else if (ah && aasp) { h = ah; asp = aasp; w = h * asp; }
else if (aw && aasp) { w = aw; asp = aasp; h = w / asp; }
else if (ah) {
h = ah;
if (cw) { w = cw; asp = w / h; }
else if (casp) { asp = casp; w = h * asp; }
else { w = h * asp; }
} else if (aw) {
w = aw;
if (ch) { h = ch; asp = w / h; }
else if (casp) { asp = casp; h = w / asp; }
else { h = w / asp; }
} else if (aasp) {
asp = aasp;
if (cw) { w = cw; h = w / asp; }
else if (ch) { h = ch; w = h * asp; }
else { w = h * asp; }
} else if (ch && cw) { h = ch; w = cw; asp = w / h; }
else if (ch && casp) { h = ch; asp = casp; w = h * asp; }
else if (cw && casp) { w = cw; asp = casp; h = w / asp; }
else if (ch) { h = ch; w = h * asp; }
else if (cw) { w = cw; h = w / asp; }
else if (casp) { asp = casp; h = w / asp; }
scope.pxwidth = Number(w); scope.pxheight = Number(h);
return relative;
};
});
// Main plot directive. Kind of complicated...
radian.directive('plot',
['processAttrs', 'calcPlotDimensions', 'addToLayout',
'$timeout', '$rootScope', 'dumpScope', 'dft', 'plotLib',
function(processAttrs, calcPlotDimensions, addToLayout,
$timeout, $rootScope, dumpScope, dft, lib)
{
'use strict';
// ID generator for plots.
var plotidgen = 0;
// We do setup work here so that we can organise things before the
// transcluded plotting directives are linked.
function preLink(scope, elm, as, transclude) {
// Oh dear. Horrible hack. Why can't Javascript be like a normal
// GUI library?
scope.watchParentSize = function(doit) {
function checkSize() {
var pw = elm.parent().width(), ph = elm.parent().height();
if (pw != scope.parentWidth || ph != scope.parentHeight)
scope.windowResize(scope, elm);
scope.parentWatchTimeout = $timeout(checkSize, 500);
};
if (!doit && scope.parentWatchTimeout) {
$timeout.cancel(scope.parentWatchTimeout);
scope.parentWatchTimeout = null;
} else if (doit && !scope.parentWatchTimeout) {
scope.parentWatchTimeout = $timeout(checkSize, 500);
scope.$on('$destroy', function() {
$timeout.cancel(scope.parentWatchTimeout);
});
}
};
// Process attributes, bringing all but a few special cases into
// Angular scope as regular variables (to be use in data access
// expressions).
processAttrs(scope, as);
scope.plotid = ++plotidgen;
scope.uielems = elm.children()[1];
scope.sizeAttrs = { width: as.width, height: as.height, aspect: as.aspect };
if (!scope.inLayout) {
scope.layoutTop = true;
if (!scope.inStack)
scope.watchParentSize(calcPlotDimensions(scope, elm, scope.sizeAttrs));
$(elm).css('width', scope.pxwidth).css('height', scope.pxheight);
scope.topLevel = elm[0];
scope.svg = elm.children()[0];
}
if (scope.inLayout || scope.inStack)
addToLayout(scope, scope, scope.layoutShare, elm);
if (as.hasOwnProperty('strokeSwitch')) scope.strokesel = 0;
// Font attributes.
scope.fontSize = Number(as.fontSize) || 12;
scope.titleFontSize = 1.25 * scope.fontSize;
if (as.titleFontSize) {
if (as.titleFontSize.indexOf('%') != -1)
scope.titleFontSize =
parseFloat(as.titleFontSize) / 100.0 * scope.fontSize;
else if (as.titleFontSize.indexOf('.') != -1)
scope.titleFontSize = Number(as.titleFontSize) * scope.fontSize;
else
scope.titleFontSize = Number(as.titleFontSize) || 1.25 * scope.fontSize;
}
scope.fontFamily = as.fontFamily || null;
scope.fontStyle = as.fontStyle || null;
scope.fontWeight = as.fontWeight || null;
scope.fontVariant = as.fontVariant || null;
scope.titleFontFamily = as.titleFontFamily || scope.fontFamily;
scope.titleFontStyle = as.titleFontStyle || scope.fontStyle;
scope.titleFontWeight = as.titleFontWeight || 'bold';
scope.titleFontVariant = as.titleFontVariant || scope.fontVariant;
// Set up view list and function for child elements to add plots.
scope.views = [];
scope.nplots = 0;
scope.switchable = [];
function ancestor(ances, desc) {
if (ances == desc) return true;
if (desc == $rootScope) return false;
return ancestor(ances, desc.$parent);
};
scope.addPlot = function(s) {
++scope.nplots;
if (s.hasOwnProperty('legendSwitch') ||
s.hasOwnProperty('label') && scope.legendSwitches) {
scope.switchable.push(s);
scope.legendSwitchEnabled = true;
}
s.enabled = true;
scope.$emit('dataChange');
s.$on('$destroy', function(e) {
if (ancestor(e.targetScope, s)) {
--scope.nplots;
s.enabled = false;
var idx = scope.switchable.indexOf(s);
if (idx != -1) scope.switchable.splice(idx, 1);
scope.$emit('dataChange');
}
});
};
transclude(scope.$new(), function (cl) { elm.append(cl); });
};
// We do the actual plotting after the transcluded plot type
// elements are linked.
function postLink(scope, elm) {
scope.topelem = elm;
if (scope.inLayout)
$(elm.children()[0]).remove();
else
$(window).resize(function () { scope.windowResize(scope, elm); });
var viewgroups = [];
var setupBrush = null;
scope.rangeExtendPixels = function(x, y) {
if (x != null)
scope.rangeXExtendPixels =
[Math.max(scope.rangeXExtendPixels[0], x[0]),
Math.max(scope.rangeXExtendPixels[1], x[1])];
if (y != null)
scope.rangeYExtendPixels =
[Math.max(scope.rangeYExtendPixels[0], y[0]),
Math.max(scope.rangeYExtendPixels[1], y[1])];
};
function redraw() {
scope.views.forEach(function(v) { draw(v, scope); });
};
function reset(suppressProcessRanges) {
scope.rangeXExtendPixels = [0, 0];
scope.rangeYExtendPixels = [0, 0];
scope.$broadcast('setupExtra');
scope.views = viewgroups.map(function(grp, i) {
grp.selectAll('.radian-plot').remove();
return setup(scope, grp, i, viewgroups.length, suppressProcessRanges);
});
scope.$broadcast('setupExtraAfter');
if (setupBrush) setupBrush();
redraw();
};
function handleAxisSwitch(axis, type) {
var xform = 'axis' + axis.toUpperCase() + 'Transform';
var rng = axis.toLowerCase() + 'range';
var saverng = 'save' + axis.toUpperCase() + 'Range';
var doReset = false;
if (scope.hasOwnProperty(saverng)) {
scope[rng] = scope[saverng];
delete scope[saverng];
doReset = true;
}
switch (type) {
case 'linear': scope[xform] = 'linear'; break;
case 'log': scope[xform] = 'log'; break;
case 'linear-0':
scope[xform] = 'linear';
scope[saverng] = angular.copy(scope[rng]);
if (scope[rng])
scope[rng][0] = 0;
else
scope[rng] = [0, null];
doReset = true;
break;
default:
throw Error("invalid axis type transition");
}
// Just do a reset if the plot range has changed. Otherwise
// redraw is triggered by the axis?Transform watcher.
if (doReset) reset(true);
}
function yAxisSwitch(e, type) { handleAxisSwitch('y', type); }
function xAxisSwitch(e, type) { handleAxisSwitch('x', type); }
scope.windowResize = function(scope, elm) {
if (!scope.inLayout || scope.layoutTop)
scope.watchParentSize(calcPlotDimensions(scope, elm, scope.sizeAttrs));
init(false);
reset();
};
function init(first) {
// Set up plot areas (including zoomers).
$(scope.topLevel).
css('width', scope.pxwidth).css('height', scope.pxheight);
var svgelm = d3.select(scope.svg);
svgelm.attr('width', scope.pxwidth).attr('height', scope.pxheight);
var mainviewgroup;
if (first)
mainviewgroup = svgelm.append('g');
else
mainviewgroup = viewgroups[0];
mainviewgroup.attr('width', scope.pxwidth).attr('height', scope.pxheight);
$(scope.uielems)
.width(scope.pxwidth + 'px')
.height(scope.pxheight + 'px');
if (first) viewgroups = [mainviewgroup];
if (!scope.sizeviewgroup) {
var s = scope;
if (scope.inStack)
while (!s.hasOwnProperty('inStack')) s = s.$parent;
s.sizeviewgroup = mainviewgroup;
s.getTextSize = function(t, attrs) {
var g = s.sizeviewgroup.append('g').attr('visibility', 'hidden');
var tstel = g.append('text').attr('x', 0).attr('y', 0)
.style('font-size', (attrs ? attrs.size : s.fontSize) + 'px')
.style('font-family', attrs ? attrs.family : s.fontFamily)
.style('font-style', attrs ? attrs.style : s.fontStyle)
.style('font-weight', attrs ? attrs.weight : s.fontWeight)
.style('font-variant', attrs ? attrs.variant : s.fontVariant)
.text(t);
var bbox = tstel[0][0].getBBox();
g.remove();
return bbox;
};
}
scope.uivisible = false;
if (scope.hasOwnProperty('zoomX')) {
var zfrac = scope.zoomX == "" ? 0.2 : +scope.zoomX;
zfrac = Math.min(0.95, Math.max(0.05, zfrac));
var zoomHeight = (scope.pxheight - 6) * zfrac;
var mainHeight = (scope.pxheight - 6) * (1 - zfrac);
var zoomviewgroup;
if (first) {
zoomviewgroup = svgelm.append('g').classed('radian-zoom-x', true);
zoomviewgroup.zoomer = true;
viewgroups.push(zoomviewgroup);
} else
zoomviewgroup = viewgroups[1];
zoomviewgroup.attr('transform', 'translate(0,' + (mainHeight + 6) + ')')
.attr('width', scope.pxwidth).attr('height', zoomHeight);
mainviewgroup.attr('height', mainHeight);
$(scope.uielems).width(scope.pxwidth + 'px').height(mainHeight + 'px');
setupBrush = function() {
var brush = d3.svg.brush().x(scope.views[1].x);
brush.on('brush', function() {
scope.views[0].x.domain(brush.empty() ?
scope.views[1].x.domain() : brush.extent());
draw(scope.views[0], scope);
});
scope.views[1].post = function(svg) {
scope.brushgroup = svg.append('g')
.attr('class', 'x brush')
.call(brush)
.selectAll('rect')
.attr('y', -6);
scope.brushgroup.attr('height', scope.views[1].realheight + 7);
}
};
}
};
if (scope.hasOwnProperty('uiAxisYTransform'))
scope.yAxisSwitchEnabled = true;
if (scope.hasOwnProperty('uiAxisXTransform'))
scope.xAxisSwitchEnabled = true;
if (scope.hasOwnProperty('uiHistogramBins')) {
scope.histogramSwitchEnabled = true;
scope.histogramBinsVar = scope.uiHistogramBins;
}
if (scope.hasOwnProperty('strokeSwitch'))
scope.strokeSwitchEnabled = true;
$timeout(function() {
// Draw plots.
init(true);
reset();
// Set up interactivity.
if (scope.hasOwnProperty('uiAxisYTransform'))
scope.$on('yAxisChange', yAxisSwitch);
if (scope.hasOwnProperty('uiAxisXTransform'))
scope.$on('xAxisChange', xAxisSwitch);
scope.$watch('axisYTransform', function(n, o) {
if (n == undefined || n == o) return;
reset();
});
scope.$watch('axisXTransform', function(n, o) {
if (n == undefined || n == o) return;
reset();
});
// Register plot data change handlers.
scope.$on('paintChange', redraw);
scope.$on('dataChange', reset);
// Register UI event handlers.
scope.$watch('strokesel', function(n,o) { if (n!=undefined) redraw(); });
scope.$watch('xidx', function(n, o) {
if (n != undefined && n != o) reset();
});
scope.$watch('yidx', function(n, o) {
if (n != undefined && n != o) reset();
});
}, 0);
};
function processRanges(scope, rangea, rangexa, rangeya,
fixedxrv, xextv, xrngv,
fixedyrv, yextv, yrngv) {
if (scope.hasOwnProperty(rangea) ||
scope.hasOwnProperty(rangexa) || scope.hasOwnProperty(rangeya)) {
var xrange, yrange;
if (scope.hasOwnProperty(rangea)) {
var ranges = scope[rangea].split(";");
if (ranges.length == 2) {
xrange = ranges[0];
yrange = ranges[1];
}
}
if (scope.hasOwnProperty(rangexa)) xrange = scope[rangexa];
if (scope.hasOwnProperty(rangeya)) yrange = scope[rangeya];
if (xrange) {
var xs = xrange.split(","), vals = xs.map(parseFloat);
var ok = false, ext = null;
if (xs.length == 2 && xs[0] && xs[1]) {
// "min,max"
if (!isNaN(vals[0]) && !isNaN(vals[1])) {
ok = true; ext = [vals[0], vals[1]];
scope[fixedxrv] = true;
scope[xextv] = ext;
}
} else if (xs.length == 1 || xs.length == 2 && !xs[1]) {
// "min" or "min,"
if (!isNaN(vals[0])) { ok = true; ext = [vals[0], null]; }
} else if (xs.length == 2 && !xs[0]) {
// ",max"
if (!isNaN(vals[1])) { ok = true; ext = [null, vals[1]]; }
}
if (ok) scope[xrngv] = ext;
}
if (yrange) {
var ys = yrange.split(","), vals = ys.map(parseFloat);
var ok = false, ext = null;
if (ys.length == 2 && ys[0] && ys[1]) {
// "min,max"
if (!isNaN(vals[0]) && !isNaN(vals[1])) {
ok = true; ext = [vals[0], vals[1]];
scope[fixedyrv] = true;
scope[yextv] = ext;
}
} else if (ys.length == 1 || ys.length == 2 && !ys[1]) {
// "min" or "min,"
if (!isNaN(vals[0])) { ok = true; ext = [vals[0], null]; }
} else if (ys.length == 2 && !ys[0]) {
// ",max"
if (!isNaN(vals[1])) { ok = true; ext = [null, vals[1]]; }
}
if (ok) scope[yrngv] = ext;
}
}
};
function makeXScaler(scope, v, hasdate, discvals, discorder) {
var xform = scope.axisXTransform || "linear";
var ext = scope.rangeXExtendPixels;
var b = ext ? ext[0] : 0, t = v.realwidth - (ext ? ext[1] : 0);
if (discvals) {
var disctmp = null;
if (scope.orderX)
disctmp = scope.orderX.split(/ *; */);
else if (discorder)
disctmp = discorder.split(/ *; */);
if (disctmp)
discvals = disctmp.map(function(s) {
var ss = s.split(/ *, */);
return ss.length == 1 ? s : ss;
});
var offsets;
if (discvals[0] instanceof Array) {
var nd = discvals[0].length;
var counts = new Array(nd);
for (var i = 0; i < nd; ++i)
counts[i] = lib.unique(discvals.map(function(v) {
return v[i];
})).length;
var dx = new Array(nd);
dx[nd - 1] = 1;
for (var i = nd - 1; i > 0; --i) dx[i - 1] = dx[i] * counts[i];
if (scope.groupX) {
var grouping = scope.groupX % nd;
var delta = scope.groupXDelta || 1.25;
for (var i = 0; i < grouping; ++i) dx[i] *= delta;
}
offsets = new Array(discvals.length);
var xs = new Array(nd);
for (var i = 0; i < discvals.length; ++i) {
var tmp = i;
for (var j = nd - 1; j >= 0; --j) {
xs[j] = tmp % counts[j];
tmp = Math.floor(tmp / counts[j]);
}
offsets[i] = 0;
for (var j = 0; j < nd; ++j) offsets[i] += xs[j] * dx[j];
}
var rescale = offsets[discvals.length - 1] / (discvals.length - 1);
for (var i = 0; i < discvals.length; ++i)
offsets[i] = offsets[i] / rescale + 1;
}
v.x =
d3.scale.linear().range([b,t]).domain([0.5, discvals.length+0.5]);
v.x.ap = function(d, i) { return v.x(v.x.oton(d), i); };
v.x.oton = function(x) {
if (x instanceof Array) {
for (var i = 0; i < discvals.length; ++i)
if (discvals[i].every(function(d, i) { return d == x[i]; }))
return offsets[i];
throw Error("Discrete value mismatch!");
} else
return discvals.indexOf(x) + 1;
};
v.x.discrete = discvals;
} else {
if (hasdate)
v.x = d3.time.scale().range([b,t]).domain(scope.xextent);
else if (xform == "log")
v.x = d3.scale.log().range([b,t]).domain(scope.xextent);
else
v.x = d3.scale.linear().range([b,t]).domain(scope.xextent);
v.x.oton = function(x) { return x; };
v.x.ap = function(d, i) { return v.x(d, i); };
}
};
function makeX2Scaler(scope, v, hasdate, discvals, discorder) {
var xform = scope.axisXTransform || "linear";
var ext = scope.rangeXExtendPixels;
var b = ext ? ext[0] : 0, t = v.realwidth - (ext ? ext[1] : 0);
if (discvals) {
var disctmp = null;
if (scope.orderX2)
disctmp = scope.orderX2.split(/ *; */);
else if (discorder)
disctmp = discorder.split(/ *; */);
if (disctmp)
discvals = disctmp.map(function(s) {
var ss = s.split(/ *, */);
return ss.length == 1 ? s : ss;
});
v.x2 = d3.scale.linear().range([b,t]).domain([0.5, discvals.length+0.5]);
var offsets;
if (discvals[0] instanceof Array) {
var nd = discvals[0].length;
var counts = new Array(nd);
for (var i = 0; i < nd; ++i)
counts[i] = lib.unique(discvals.map(function(v) {
return v[i];
})).length;
var dx = new Array(nd);
dx[nd - 1] = 1;
for (var i = nd - 1; i > 0; --i) dx[i - 1] = dx[i] * counts[i];
if (scope.groupX) {
var grouping = scope.groupX2 % nd;
var delta = scope.groupX2Delta || 1.25;
for (var i = 0; i < grouping; ++i) dx[i] *= delta;
}
offsets = new Array(discvals.length);
var xs = new Array(nd);
for (var i = 0; i < discvals.length; ++i) {
var tmp = i;
for (var j = nd - 1; j >= 0; --j) {
xs[j] = tmp % counts[j];
tmp = Math.floor(tmp / counts[j]);
}
offsets[i] = 0;
for (var j = 0; j < nd; ++j) offsets[i] += xs[j] * dx[j];
}
var rescale = offsets[discvals.length - 1] / (discvals.length - 1);
for (var i = 0; i < discvals.length; ++i)
offsets[i] = offsets[i] / rescale + 1;
}
v.x2.oton = function(x) {
if (x instanceof Array) {
for (var i = 0; i < discvals.length; ++i)
if (discvals[i].every(function(d, i) { return d == x[i]; }))
return offsets[i];
throw Error("Discrete value mismatch!");
} else
return discvals.indexOf(x) + 1;
};
v.x2.discrete = discvals;
v.x2.discmap = function(x) { return discvals.indexOf(x) + 1; };
} else if (hasdate)
v.x2 = d3.time.scale().range([b,t]).domain(scope.x2extent);
else if (xform == "log")
v.x2 = d3.scale.log().range([b,t]).domain(scope.x2extent);
else
v.x2 = d3.scale.linear().range([b,t]).domain(scope.x2extent);
};
function makeYScaler(scope, v) {
var xform = scope.axisYTransform || "linear";
var ext = scope.rangeYExtendPixels;
var b = ext ? ext[0] : 0, t = v.realheight - (ext ? ext[1] : 0);
if (xform == "log")
v.y = d3.scale.log().range([t,b]).domain(scope.yextent);
else
v.y = d3.scale.linear().range([t,b]).domain(scope.yextent);
};
function makeY2Scaler(scope, v) {
var xform = scope.axisYTransform || "linear";
var ext = scope.rangeYExtendPixels;
var b = ext ? ext[0] : 0, t = v.realheight - (ext ? ext[1] : 0);
if (xform == "log")
v.y2 = d3.scale.log().range([t,b]).domain(scope.y2extent);
else
v.y2 = d3.scale.linear().range([t,b]).domain(scope.y2extent);
};
// function setupUI(scope, viewgroup) {
function setupUI(scope) {
function uiOn(e) { scope.$apply('uivisible = true'); };
function uiOff(e) {
var elem = $(e.relatedTarget), chk = $(scope.uielems), outside = true;
while (elem[0] && elem[0].parentElement) {
if (elem[0] == chk[0]) { outside = false; break; }
elem = elem.parent();
}
if (outside) scope.$apply('uivisible = false');
};
$(scope.uielems).mouseenter(uiOn).mouseleave(uiOff);
};
function setup(scope, viewgroup, idx, nviews, suppressProcessRanges) {
var plotgroup = viewgroup.append('g').classed('radian-plot', true);
var v = { group: viewgroup, plotgroup: plotgroup };
if (viewgroup.hasOwnProperty('zoomer'))
v.noTitle = true;
else
setupUI(scope);
// Determine data ranges to use for plot -- either as specified in
// RANGE-X, RANGE-Y or RANGE (for X1 and Y1 axes) and RANGE-X2,
// RANGE-Y2 or RANGE2 (for X2 and Y2 axes) attributes on the plot
// element, or the union of the data ranges for all plots.
if (!suppressProcessRanges) {
processRanges(scope, 'range', 'rangeX', 'rangeY',
'fixedXRange', 'xextent', 'xrange',
'fixedYRange', 'yextent', 'yrange');
processRanges(scope, 'range2', 'rangeX2', 'rangeY2',
'fixedX2Range', 'x2extent', 'x2range',
'fixedY2Range', 'y2extent', 'y2range');
if (scope.axisYTransform == 'linear-0') {
if (!scope.hasOwnProperty('saveYRange'))
scope.saveYRange = angular.copy(scope.yrange);
if (scope.yrange)
scope.yrange[0] = 0;
else
scope.yrange = [0, null];
}
if (scope.axisXTransform == 'linear-0') {
if (!scope.hasOwnProperty('saveXRange'))
scope.saveXRange = angular.copy(scope.xrange);
if (scope.xrange)
scope.xrange[0] = 0;
else
scope.xrange = [0, null];
}
scope.$broadcast('setupRanges', scope);
}
function simpleExt(a) {
if (typeof a[0] == 'string')
return [0.5, lib.unique(a).length + 0.5];
else
return d3.extent(a);
};
function aext(d) {
if (d[0] instanceof Array) {
return d3.merge(d.map(function(a) { return simpleExt(a); }));
} else
return simpleExt(d);
};
function aext2(d, d2, d2min, d2max) {
if (d[0] instanceof Array) {
return d3.merge(d.map(function(a) {
return d3.extent(a.filter(function(x, i) {
return d2[i] >= d2min && d2[i] <= d2max;
}));
}));
} else
return d3.extent(d.filter(function(x, i) {
return d2[i] >= d2min && d2[i] <= d2max;
}));
};
var xexts = [], yexts = [], hasdate = false;
var anyxdisc = false, anyxcont = false;
var discx = null, discorder = null;
var xextend = [0, 0], yextend = [0, 0];
var x2exts = [], y2exts = [], hasdate2 = false;
var anyx2disc = false, anyx2cont = false;
var discx2 = null, discorder2 = null;
dft(scope, function(s) {
if (!scope.fixedXRange && s.enabled && s.x)
xexts = xexts.concat(aext(s.x));
if (!scope.fixedX2Range && s.enabled && s.x2)
x2exts = x2exts.concat(aext(s.x2));
if (!scope.fixedYRange && s.enabled && s.y) {
if (scope.fixedXRange)
yexts = yexts.concat(aext2(s.y, s.x,
scope.xextent[0], scope.xextent[1]));
else yexts = yexts.concat(aext(s.y));
}
if (!scope.fixedY2Range && s.enabled && s.y2) {
if (scope.fixedXRange)
y2exts = y2exts.concat(aext2(s.y2, s.x,
scope.xextent[0], scope.xextent[1]));
else y2exts = y2exts.concat(aext(s.y2));
}
if (s.x && (s.x.metadata && s.x.metadata.format == 'date' ||
s.x instanceof Array && s.x[0] instanceof Date))
hasdate = true;
if (s.x && s.x instanceof Array) {
// There are three possible cases where we want to treat the
// X-values as discrete:
// 1. String values.
// 2. Array values (indicating parallel zipped data arrays
// for hierarchical treatment).
// 3. When the X-data is explicitly marked as being discrete
// -- this is needed to deal with the case where we have
// integer values and want to treat them as discrete
// values.
if (typeof s.x[0] == 'string' || // Case #1
s.x[0] instanceof Array || // Case #2
s.discreteX) { // Case #3
// The unique function in the Radian library will work with
// array-valued entries without a problem.
var vals = lib.unique(s.x);
vals.sort();
if (discx) {
if (discx.length != vals.length ||
discx.some(function(x, i) {
if (x instanceof Array)
return x.some(function(y, j) { return y != vals[i][j]; });
else
return x != vals[i];
}))
throw Error("Incompatible discrete X values");
} else discx = vals;
if (s.x.metadata && s.x.metadata.categoryOrder)
discorder = s.x.metadata.categoryOrder;
anyxdisc = true;
} else anyxcont = true;
}
if (s.x2 && (s.x2.metadata && s.x2.metadata.format == 'date' ||
s.x2 instanceof Array && s.x2[0] instanceof Date))
hasdate2 = true;
if (s.x2 && s.x2 instanceof Array) {
if (typeof s.x2[0] == 'string' || // Case #1
s.x2[0] instanceof Array || // Case #2
s.discreteX2) { // Case #3
var vals = lib.unique(s.x2);
vals.sort();
if (discx2) {
if (discx2.length != vals.length ||
discx2.some(function(x, i) {
if (x instanceof Array)
return x.some(function(y, j) { return y != vals[i][j]; });
else
return x != vals[i];
}))
throw Error("Incompatible discrete X2 values");
} else discx2 = vals;
if (s.x2.metadata && s.x2.metadata.categoryOrder)
discorder2 = s.x2.metadata.categoryOrder;
anyx2disc = true;
} else anyx2cont = true;
}
if (s.rangeXExtend) {
xextend[0] = Math.max(xextend[0], s.rangeXExtend[0]);
xextend[1] = Math.max(xextend[1], s.rangeXExtend[1]);
}
if (s.rangeYExtend) {
yextend[0] = Math.max(yextend[0], s.rangeYExtend[0]);
yextend[1] = Math.max(yextend[1], s.rangeYExtend[1]);
}
if (s.rangeXExtendPixels) scope.rangeXExtendPixels = s.rangeXExtendPixels;
if (s.rangeYExtendPixels) scope.rangeYExtendPixels = s.rangeYExtendPixels;
});
if (anyxdisc && anyxcont)
throw Error("Can't mix discrete and continuous X values");
if (anyx2disc && anyx2cont)
throw Error("Can't mix discrete and continuous X2 values");
if (!scope.fixedXRange && xexts.length > 0) {
scope.xextent = d3.extent(xexts);
if (scope.xrange) {
if (scope.xrange[0] != null)
scope.xextent[0] = Math.min(scope.xextent[0], scope.xrange[0]);
if (scope.xrange[1] != null)
scope.xextent[1] = Math.max(scope.xextent[1], scope.xrange[1]);
}
if (!hasdate) {
scope.xextent[0] -= xextend[0];
scope.xextent[1] += xextend[1];
}
}
if (!scope.fixedYRange && yexts.length > 0) {
scope.yextent = d3.extent(yexts);
if (scope.yrange) {
if (scope.yrange[0] != null) scope.yextent[0] = scope.yrange[0];
if (scope.yrange[1] != null) scope.yextent[1] = scope.yrange[1];
}
scope.yextent[0] -= yextend[0];
scope.yextent[1] += yextend[1];
}
if (!scope.fixedX2Range && x2exts.length > 0) {
scope.x2extent = d3.extent(x2exts);
if (scope.x2range) {
if (scope.x2range[0] != null)
scope.x2extent[0] = Math.min(scope.x2extent[0], scope.x2range[0]);
if (scope.x2range[1] != null)
scope.x2extent[1] = Math.max(scope.x2extent[1], scope.x2range[1]);
}
// scope.x2extent[0] -= x2extend[0];
// scope.x2extent[1] += x2extend[1];
}
if (!scope.fixedY2Range && y2exts.length > 0) {
scope.y2extent = d3.extent(y2exts);
if (scope.y2range) {
if (scope.y2range[0] != null)
scope.y2extent[0] = Math.min(scope.y2extent[0], scope.y2range[0]);
if (scope.y2range[1] != null)
scope.y2extent[1] = Math.max(scope.y2extent[1], scope.y2range[1]);
}
// scope.y2extent[0] -= y2extend[0];
// scope.y2extent[1] += y2extend[1];
}
// Extract plot attributes.
v.xaxis = !scope.axisX || scope.axisX != 'off';
v.yaxis = !scope.axisY || scope.axisY != 'off';
v.x2axis = !!(scope.x2extent && (!scope.axisX2 || scope.axisX2 != 'off'));
v.y2axis = !!(scope.y2extent && (!scope.axisY2 || scope.axisY2 != 'off'));
var showXAxisLabel = (nviews == 1 || nviews == 2 && idx == 1) &&
(!scope.axisXLabel || scope.axisXLabel != 'off');
var showYAxisLabel = !scope.axisYLabel || scope.axisYLabel != 'off';
var showX2AxisLabel = (nviews == 1 || nviews == 2 && idx == 1) &&
(!scope.axisX2Label || scope.axisX2Label != 'off');
var showY2AxisLabel = !scope.axisY2Label || scope.axisY2Label != 'off';
v.margin = { top: +scope.topMargin || 2,
right: +scope.rightMargin || 2,
bottom: +scope.bottomMargin || 2,
left: +scope.leftMargin || 2 };
v.margin.top += 0.5 * scope.fontSize;
v.title = scope.title;
// Set up top and bottom plot margins.
if (scope.inStack) v.noTitle = true;
var axisspace = 15;
var del1 = axisspace + (+scope.fontSize);
var del2 = 5 + (+scope.fontSize);
var del3 = Math.floor(2.5 * scope.fontSize);
if (v.xaxis) v.margin.bottom += del1 + (showXAxisLabel ? del2 : 0);
if (v.x2axis) v.margin.top += del1 + (showX2AxisLabel ? del2 : 0);
if (v.title && !v.noTitle) v.margin.top += del3;
v.realheight = v.group.attr('height') - v.margin.top - v.margin.bottom;
v.outh = v.realheight + v.margin.top + v.margin.bottom;
// Set up D3 Y data ranges.
if (scope.yextent) makeYScaler(scope, v);
if (scope.y2extent) makeY2Scaler(scope, v);
// Set up left and right plot margins.
var yoffset = del3, y2offset = del3;
if (v.yaxis && v.y) {
var tmp = v.y.copy();
var fmt = scope.axisYFormat ? d3.format(scope.axisYFormat) : null;
var nticks;
if (scope.axisYTicks) {
if (scope.axisYTicks instanceof Array)
nticks = scope.axisYTicks.length;
else
nticks = scope.axisYTicks;
}
else
nticks = v.group.attr('height') / 36;
var fmtfn = fmt ? tmp.tickFormat(nticks, fmt) : tmp.tickFormat(nticks);
var tst = '';
tmp.ticks(nticks).map(fmtfn).forEach(function(s) {
if (s.length > tst.length) tst = s;
});
tst = tst.replace(/[0-9]/g, '0');
var tstsz = scope.getTextSize(tst);
yoffset = Math.max(del3, axisspace + tstsz.width);
}
if (v.y2axis && v.y2) {
var tmp = v.y2.copy();
var fmt = scope.axisY2Format ? d3.format(scope.axisY2Format) : null;
var nticks;
if (scope.axisY2Ticks) {
if (scope.axisY2Ticks instanceof Array)
nticks = scope.axisY2Ticks.length;
else
nticks = scope.axisY2Ticks;
}
else
nticks = v.group.attr('height') / 36;
var fmtfn = fmt ? tmp.tickFormat(nticks, fmt) : tmp.tickFormat(nticks);
var tst = '';
tmp.ticks(nticks).map(fmtfn).forEach(function(s) {
if (s.length > tst.length) tst = s;
});
tst = tst.replace(/[0-9]/g, '0');
var tstsz = scope.getTextSize(tst);
y2offset = Math.max(del3, axisspace + tstsz.width);
}
if (v.yaxis) v.margin.left += yoffset + (showYAxisLabel ? del2 : 0);
if (v.y2axis) v.margin.right += y2offset + (showY2AxisLabel ? del2 : 0);
v.realwidth = v.group.attr('width') - v.margin.left - v.margin.right;
v.outw = v.realwidth + v.margin.left + v.margin.right;
// Set up D3 X data ranges.
if (scope.xextent) makeXScaler(scope, v, hasdate, discx, discorder);
if (scope.x2extent) makeX2Scaler(scope, v, hasdate2, discx2, discorder2);
// Figure out axis labels.
function axisLabel(labelText, v, idxvar, selectvar, def) {
var idx0 = null;
if (!labelText) {
dft(scope, function(s) {
if (!labelText)
if (s[v] && s[v].metadata && s[v].metadata.label) {
labelText = s[v].metadata.label;
if (s[v].metadata.units)
labelText += ' (' + s[v].metadata.units + ')';
}
idx0 = idx0 || s[idxvar];
});
if (!labelText && scope[selectvar]) {
var labs = scope[selectvar].split(',');
labelText = labs[idx0];
}
if (!labelText) labelText = def;
}
return labelText;
};
if (showXAxisLabel)
v.xlabel = axisLabel(scope.axisXLabel, 'x', 'xidx', 'selectX', 'X Axis');
if (showYAxisLabel)
v.ylabel = axisLabel(scope.axisYLabel, 'y', 'yidx', 'selectY', 'Y Axis');
if (showX2AxisLabel)
v.x2label = axisLabel(scope.axisX2Label, 'x2',
'xidx', 'selectX2', 'X2 Axis');
if (showY2AxisLabel)
v.y2label = axisLabel(scope.axisY2Label, 'y2',
'yidx', 'selectY2', 'Y2 Axis');
if (idx == 0) {
var svgelm = d3.select(scope.svg);
v.clip = 'mainclip' + scope.plotid;
svgelm.select('#' + v.clip).remove();
svgelm.append('defs').append('clipPath')
.attr('id', v.clip).append('rect')
.attr('width', v.realwidth).attr('height', v.realheight);
}
return v;
};
function setFont(lab, scope) {
if (scope.fontFamily) lab.style('font-family', scope.fontFamily);
if (scope.fontStyle) lab.style('font-style', scope.fontStyle);
if (scope.fontWeight) lab.style('font-weight', scope.fontWeight);
if (scope.fontVariant) lab.style('font-variant', scope.fontVariant);
};
function defaultScaleFormat(xform, xs, m) {
if (xform && xform == 'log') return d3.format(".0e");
var extent = xs.domain();
var span = extent[1] - extent[0];
var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
var err = m / span * step;
if (err <= .15) step *= 10;
else if (err <= .35) step *= 5;
else if (err <= .75) step *= 2;
var n = Math.max(0, -Math.floor(Math.log(step) / Math.LN10 + .01));
return d3.format(n > 6 ? ".2e" : (",." + n + "f"));
};
function makeAxis(sc, v, ax, tickDefault) {
// Axis orientation.
var ori;
switch (ax) {
case 'x': ori = 'bottom'; break;
case 'x2': ori = 'top'; break;
case 'y': ori = 'left'; break;
case 'y2': ori = 'right'; break;
}
// Create base axis object.
var axis = d3.svg.axis().scale(v[ax]).orient(ori);
// Tick padding.
var axatt = ax.toUpperCase();
var paddingAttr = 'axis' + axatt + 'TickPadding';
var padding = sc[paddingAttr] ? sc[paddingAttr] : sc.tickPadding;
var padding_delta = 0;
if (padding) {
axis.tickPadding(+padding);
padding_delta = +padding - 3;
}
// Process tick size information: there are global tick-sizes and
// tick-size, minor-tick-size and end-tick-size attributes, and
// there are also per-axis variants of these.
var tickSizeAttr = 'axis' + axatt + 'TickSize';
var minorTickSizeAttr = 'axis' + axatt + 'MinorTickSize';
var endTickSizeAttr = 'axis' + axatt + 'EndTickSize';
var tickSizesAttr = 'axis' + axatt + 'TickSizes';
var norm_val = 6, minor_val = 6, end_val = 6;
if (sc.tickSizes) {
var vals = sc.tickSizes.split(/ *, */);
if (vals.length >= 3) {
norm_val = vals[0]; minor_val = vals[1]; end_val = vals[2];
} else if (vals.length == 2) {
norm_val = minor_val = vals[0]; end_val = vals[1];
} else if (vals.length == 1)
norm_val = minor_val = end_val = vals[0];
}
if (sc.tickSize) norm_val = sc.tickSize;
if (sc.minorTickSize) minor_val = sc.minorTickSize;
if (sc.endTickSize) end_val = sc.endTickSize;
if (sc[tickSizesAttr]) {
var vals = sc[tickSizesAttr].split(/ *, */);
if (vals.length >= 3) {
norm_val = vals[0]; minor_val = vals[1]; end_val = vals[2];
} else if (vals.length == 2) {
norm_val = minor_val = vals[0]; end_val = vals[1];
} else if (vals.length == 1)
norm_val = minor_val = end_val = vals[0];
}
if (sc[tickSizeAttr]) norm_val = sc[tickSizeAttr];
if (sc[minorTickSizeAttr]) minor_val = sc[minorTickSizeAttr];
if (sc[endTickSizeAttr]) end_val = sc[endTickSizeAttr];
if (v[ax].discrete) end_val = 0;
axis.tickSize(norm_val, minor_val, end_val);
// Special treatment for discrete axes.
if (v[ax].discrete) {
var tickvals = [], ticklabs = [];
v[ax].discrete.forEach(function(x, i) {
tickvals.push(v[ax].oton(x));
ticklabs.push(x);
});
axis.tickValues(tickvals);
axis.tickFormat(function(x) {
var i = tickvals.indexOf(x);
return x == -1 ? '' : ticklabs[i];
});
axis.tickSize();
return [axis, padding_delta];
}
// Do we need to use a date/time format?
var dformat = '%Y-%m-%d';
var has_date = false;
dft(sc, function(s) {
var d = s[ax];
if (d && (d.metadata && d.metadata.format == 'date' ||
d instanceof Array && d[0] instanceof Date)) {
if (d.metadata && d.metadata.dateFormat)
dformat = d.metadata.dateFormat;
has_date = true;
}
});
// Figure out settings for ticks and tick format.
var ticksAttr = 'axis' + axatt + 'Ticks';
var fmtAttr = 'axis' + axatt + 'Format';
var xformAttr = 'axis' + axatt + 'Transform';
var ticks, fmt;
ticks = sc[ticksAttr] ? sc[ticksAttr] : tickDefault;
var explicit_ticks = false, explicit_labels = false;
var tickvals = [], ticklabs = [];
if (ticks instanceof Array) {
// We have explicit tick values.
explicit_ticks = true;
ticks.forEach(function(t) {
if (t instanceof Array) {
tickvals.push(t[0]);
ticklabs.push(t[1]);
explicit_labels = true;
} else {
tickvals.push(t);
ticklabs.push(t);
}
});
ticks = 100 * ticks.length;
}
if (has_date)
fmt = d3.time.format(sc[fmtAttr] ? sc[fmtAttr] : dformat);
else
fmt = sc[fmtAttr] ? d3.format(sc[fmtAttr]) :
defaultScaleFormat(sc[xformAttr], v[ax], ticks);
if (explicit_ticks) {
axis.tickValues(tickvals);
if (explicit_labels)
axis.tickFormat(function(x) {
var i = tickvals.indexOf(x);
return x == -1 ? '' : ticklabs[i];
});
else
axis.tickFormat(fmt);
} else if (has_date) {
var tickFn = null, tickNum = ticks;
if (isNaN(Number(ticks))) {
tickNum = parseFloat(ticks);
var tickUnit = '';
for (var i = ticks.length - 1; i >= 0; --i)
if ("0123456789.".indexOf(ticks.charAt(i)) != -1) {
tickUnit = ticks.substr(i + 1);
break;
}
switch (tickUnit) {
case 's': tickFn = d3.time.seconds; break;
case 'min': tickFn = d3.time.minutes; break;
case 'hr': tickFn = d3.time.hours; break;
case 'd': tickFn = d3.time.days; break;
case 'week': tickFn = d3.time.weeks; break;
case 'mon': tickFn = d3.time.months; break;
case 'year': tickFn = d3.time.years; break;
}
}
if (tickFn)
axis.ticks(tickFn, tickNum);
else
axis.ticks(tickNum);
axis.tickFormat(fmt);
} else if (sc[fmtAttr] || sc[xformAttr]) {
axis.ticks(ticks, fmt);
} else {
axis.ticks(ticks);
axis.tickFormat(fmt);
}
// Deal with tick sub-division, as indicated by the minorTicks
// attributes.
var minorTicksAttr = 'axis' + axatt + 'MinorTicks';
var minor = sc[minorTicksAttr] ? sc[minorTicksAttr] : sc.minorTicks;
if (minor) axis.tickSubdivide(minor);
return [axis, padding_delta];
};
function jitter(xs, scale, jit) {
var jsize = jit ? parseFloat(jit) : 0.05, j = [];
if (isNaN(jsize)) jsize = 0.1;
xs.forEach(function(x) { j.push((Math.random() * 2 - 1) * jsize); });
var ret = function(d, i) { return scale(d + j[i]); };
ret.oton = scale.oton;
ret.ap = function(d, i) { return scale(scale.oton(d) + j[i], i); };
return ret;
};
function draw(v, scope) {
// Clean out any pre-existing plots.
$(v.plotgroup[0]).empty();
// Set up plot margins.
v.plotgroup.attr('width', v.outw).attr('height', v.outh);
v.innergroup = v.plotgroup.append('g')
.attr('width', v.realwidth).attr('height', v.realheight)
.attr('transform', 'translate(' + v.margin.left + ',' +
v.margin.top + ')');
if (v.clip) v.innergroup.attr('clip-path', 'url(#' + v.clip + ')');
// Draw D3 axes.
var del1 = Math.floor(scope.fontSize / 3.0);
var del2 = Math.floor(3.0 * scope.fontSize);
if (v.xaxis && v.x) {
var ax = makeAxis(scope, v, 'x', v.plotgroup.attr('width') / 100);
var axis = ax[0], padding_delta = ax[1];
v.plotgroup.append('g').attr('class', 'axis')
.style('font-size', scope.fontSize + 'px')
.attr('transform', 'translate(' + v.margin.left + ',' +
(+v.realheight + v.margin.top + del1) + ')')
.call(axis);
if (v.xlabel) {
var lab = v.plotgroup.append('g').attr('class', 'axis-label')
.attr('transform', 'translate(' +
(+v.margin.left + v.realwidth / 2) +
',' + (+v.realheight + v.margin.top) + ')')
.append('text')
.attr('x', 0).attr('y', del2 + padding_delta)
.style('font-size', scope.fontSize + 'px')
.attr('text-anchor', 'middle').text(v.xlabel);
setFont(lab, scope);
}
}
if (v.x2axis && v.x2) {
var ax = makeAxis(scope, v, 'x2', v.plotgroup.attr('width') / 100);
var axis = ax[0], padding_delta = ax[1];
v.plotgroup.append('g').attr('class', 'axis')
.style('font-size', scope.fontSize + 'px')
.attr('transform', 'translate(' + v.margin.left + ',' +
(+v.margin.top + del1) + ')')
.call(axis);
if (v.x2label) {
var lab = v.plotgroup.append('g').attr('class', 'axis-label')
.attr('transform', 'translate(' +
(+v.margin.left + v.realwidth / 2) + ',' +
(+v.margin.top) + ')')
.append('text')
.attr('x', 0).attr('y', del2 - padding_delta)
.style('font-size', scope.fontSize + 'px')
.attr('text-anchor', 'middle').text(v.x2label);
setFont(lab, scope);
}
}
if (v.yaxis && v.y) {
var ax = makeAxis(scope, v, 'y', v.plotgroup.attr('height') / 36);
var axis = ax[0], padding_delta = ax[1];
v.plotgroup.append('g').attr('class', 'axis')
.style('font-size', scope.fontSize + 'px')
.attr('transform', 'translate(' + (+v.margin.left - del1) + ',' +
(+v.margin.top) + ')')
.call(axis);
if (v.ylabel) {
var xpos = +scope.fontSize, ypos = +v.margin.top + v.realheight / 2;
var lab = v.plotgroup.append('g').attr('class', 'axis-label')
.append('text')
.attr('x', xpos - padding_delta).attr('y', ypos)
.attr('transform', 'rotate(-90,' + xpos + ',' + ypos + ')')
.style('font-size', scope.fontSize + 'px')
.attr('text-anchor', 'middle').text(v.ylabel);
setFont(lab, scope);
}
}
if (v.y2axis && v.y2) {
var ax = makeAxis(scope, v, 'y2', v.plotgroup.attr('height') / 36);
var axis = ax[0], padding_delta = ax[1];
v.plotgroup.append('g').attr('class', 'axis')
.style('font-size', scope.fontSize + 'px')
.attr('transform', 'translate(' +
(+v.realwidth + v.margin.left) + ',' +
(+v.margin.top) + ')')
.call(axis);
if (v.y2label) {
var xpos = v.realwidth + v.margin.left + v.margin.right -
scope.fontSize;
var ypos = +v.margin.top + v.realheight / 2;
var lab = v.plotgroup.append('g').attr('class', 'axis-label')
.append('text')
.attr('x', xpos + padding_delta).attr('y', ypos)
.attr('transform', 'rotate(-90,' + xpos + ',' + ypos + ')')
.style('font-size', scope.fontSize + 'px')
.attr('text-anchor', 'middle').text(v.y2label);
setFont(lab, scope);
}
}
setFont(d3.selectAll('.axis text'), scope);
// Plot title.
v.plotgroup.selectAll('g.no-data').remove();
if (scope.nplots == 0 && v == scope.views[0] && scope.noData)
v.plotgroup.append('g').attr('class', 'no-data').append('text')
.attr('x', v.outw / 2).attr('y', v.outh / 2)
.attr('text-anchor', 'middle').text(scope.noData);
if (v.title && !v.noTitle) {
var t = v.plotgroup.append('g').attr('class', 'axis-label')
.attr('transform', 'translate(' +
(+v.margin.left + v.realwidth / 2) + ',0)')
.append('text')
.attr('x', 0).attr('y', Math.floor(1.35 * scope.titleFontSize))
.style('font-size', Math.floor(scope.titleFontSize) + 'px')
.attr('text-anchor', 'middle').text(v.title);
if (scope.titleFontFamily) t.style('font-family', scope.titleFontFamily);
if (scope.titleFontStyle) t.style('font-style', scope.titleFontStyle);
if (scope.titleFontWeight) t.style('font-weight', scope.titleFontWeight);
if (scope.titleFontVariant)
t.style('font-variant', scope.titleFontVariant);
}
// Loop over plots, calling their draw functions one by one.
if (v.x && v.y || v.x2 && v.y || v.x && v.y2 || v.x2 && v.y2) {
dft(scope, function(s) {
if (s.draw && s.enabled) {
var xvar = false, yvar = false, xdiscrete = false;
var xs, ys;
if (s.x) { xvar = 'x'; xs = v.x; xdiscrete = !!v.x.discrete; }
if (s.x2) { xvar = 'x2'; xs = v.x2; xdiscrete = !!v.x2.discrete; }
if (s.y) { yvar = 'y'; ys = v.y; }
if (s.y2) { yvar = 'y2'; ys = v.y2; }
if (!xs) xs = v.x;
if (!ys) ys = v.y;
if (xvar && yvar ||
s.checkPlottable && s.checkPlottable(xvar, yvar)) {
// Append SVG group for this plot and draw the plot into it.
var g = v.innergroup.append('g');
var x = xvar ? ((s[xvar][0] instanceof Array && !v.x.discrete) ?
s[xvar][s.xidx ? s.xidx : 0] : s[xvar]) : undefined;
if (s.hasOwnProperty('jitterX') && x) xs = jitter(x, xs, s.jitterX);
var y = yvar ? ((s[yvar][0] instanceof Array) ?
s[yvar][s.yidx ? s.yidx : 0] : s[yvar]) : undefined;
if (s.hasOwnProperty('jitterY') && y) ys = jitter(y, ys, s.jitterY);
s.draw(g, x, xs, y, ys, s, v.realwidth, v.realheight,
yvar == 'y2' ? 2 : 1);
s.$on('$destroy', function() { g.remove(); });
}
}
});
if (v.post) v.post(v.innergroup);
}
};
return {
restrict: 'E',
template:
['<div class="radian">',
'<svg></svg>',
'<div class="radian-ui">',
'<radian-legend-switch ng-show="legendSwitchEnabled">',
'</radian-legend-switch>',
'<div ng-show="uivisible">',
'<radian-histogram-switch ng-show="histogramSwitchEnabled">',
'</radian-histogram-switch>',
'<radian-axis-switch axis="y" ng-show="yAxisSwitchEnabled">',
'</radian-axis-switch>',
'<radian-axis-switch axis="x" ng-show="xAxisSwitchEnabled">',
'</radian-axis-switch>',
'<radian-stroke-switch ng-show="strokeSwitchEnabled">',
'</radian-stroke-switch>',
'</div>',
'</div>',
'</div>'].join(""),
replace: true,
transclude: true,
scope: true,
compile: function(elm, as, trans) {
return { pre: function(s, e, a) { preLink(s, e, a, trans); },
post: postLink };
}
};
}]);
// Link function shared by most simple plotting directives. Does
// attribute processing, hides HTML element, sets up drawing function
// and sets up event emitters for data and paint changes.
radian.factory('plotTypeLink',
['processAttrs', '$timeout',
function(processAttrs, $timeout)
{
var paintas = [ 'orientation', 'fill', 'fillOpacity', 'label',
'marker', 'markerSize', 'stroke', 'strokeOpacity',
'strokeWidth' ];
return function(typ, scope, elm, as, draw) {
processAttrs(scope, as);
elm.hide();
scope.draw = draw;
scope.plotType = typ;
scope.$parent.addPlot(scope);
scope.xchange = scope.ychange = false;
function emitChange() {
var emit = scope.xchange || scope.ychange;
scope.xchange = scope.ychange = false;
if (emit) scope.$emit('dataChange', scope);
}
scope.$watch('x', function(n, o) {
if (n == undefined || n === o || scope.xchange) return;
scope.xchange = true;
$timeout(emitChange);
});
scope.$watch('y', function(n, o) {
if (n == undefined || n === o || scope.ychange) return;
scope.ychange = true;
$timeout(emitChange);
});
paintas.forEach(function(a) {
if (scope.hasOwnProperty(a))
scope.$watch(a, function() { scope.$emit('paintChange', scope); });
});
};
}]);
// Simple directive just to wrap inner plotting directives that share
// options. Brings any attributes into scope and transcludes inner
// plot directives.
radian.directive('plotOptions', ['processAttrs', function(processAttrs)
{
'use strict';
return {
restrict: 'E',
template: '<div></div>',
replace: true,
transclude: true,
scope: true,
compile: function(elm, as, trans) {
return { pre: function(s, e, a) {
processAttrs(s, a);
trans(s.$new(), function (cl) { e.append(cl); });
} };
}
};
}]);
// This file contains a modified version of the estraverse library,
// set up for easy use with Angular and supporting some extensions to
// normal JavaScript expression syntax.
//
// ORIGINAL LICENSE COMMENT:
//
/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
radian.factory('estraverse', function()
{
'use strict';
var Syntax,
isArray,
VisitorOption,
VisitorKeys,
wrappers;
Syntax = {
AssignmentExpression: 'AssignmentExpression',
ArrayExpression: 'ArrayExpression',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DebuggerStatement: 'DebuggerStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
EmptyStatement: 'EmptyStatement',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
Identifier: 'Identifier',
IfStatement: 'IfStatement',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
Program: 'Program',
Property: 'Property',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement'
};
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray(array) {
return Object.prototype.toString.call(array) === '[object Array]';
};
}
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
ArrayExpression: ['elements'],
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
CallExpression: ['callee', 'arguments'],
CatchClause: ['param', 'body'],
ConditionalExpression: ['test', 'consequent', 'alternate'],
ContinueStatement: ['label'],
DebuggerStatement: [],
DirectiveStatement: [],
DoWhileStatement: ['body', 'test'],
EmptyStatement: [],
ExpressionStatement: ['expression'],
ForStatement: ['init', 'test', 'update', 'body'],
ForInStatement: ['left', 'right', 'body'],
FunctionDeclaration: ['id', 'params', 'body'],
FunctionExpression: ['id', 'params', 'body'],
Identifier: [],
IfStatement: ['test', 'consequent', 'alternate'],
Literal: [],
LabeledStatement: ['label', 'body'],
LogicalExpression: ['left', 'right'],
MemberExpression: ['object', 'property'],
PluckExpression: ['object', 'property'],
PaletteExpression: [],
InterpolatorExpression: [],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
Program: ['body'],
Property: ['key', 'value'],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
ThisExpression: [],
ThrowStatement: ['argument'],
TryStatement: ['block', 'handlers', 'finalizer'],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
WithStatement: ['object', 'body']
};
VisitorOption = {
Break: 1,
Skip: 2
};
wrappers = {
PropertyWrapper: 'Property'
};
function traverse(top, visitor) {
var worklist, leavelist, node, nodeType, ret, current, current2, candidates, candidate, marker = {};
worklist = [ top ];
leavelist = [ null ];
while (worklist.length) {
node = worklist.pop();
nodeType = node.type;
if (node === marker) {
node = leavelist.pop();
if (visitor.leave) {
ret = visitor.leave(node, leavelist[leavelist.length - 1]);
} else {
ret = undefined;
}
if (ret === VisitorOption.Break) {
return;
}
} else if (node) {
if (wrappers.hasOwnProperty(nodeType)) {
node = node.node;
nodeType = wrappers[nodeType];
}
if (visitor.enter) {
ret = visitor.enter(node, leavelist[leavelist.length - 1]);
} else {
ret = undefined;
}
if (ret === VisitorOption.Break) {
return;
}
worklist.push(marker);
leavelist.push(node);
if (ret !== VisitorOption.Skip) {
candidates = VisitorKeys[nodeType];
current = candidates.length;
while ((current -= 1) >= 0) {
candidate = node[candidates[current]];
if (candidate) {
if (isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (candidate[current2]) {
if(nodeType === Syntax.ObjectExpression && 'properties' === candidates[current] && null == candidates[current].type) {
worklist.push({type: 'PropertyWrapper', node: candidate[current2]});
} else {
worklist.push(candidate[current2]);
}
}
}
} else {
worklist.push(candidate);
}
}
}
}
}
}
}
function replace(top, visitor) {
var worklist, leavelist, node, nodeType, target, tuple, ret, current, current2, candidates, candidate, marker = {}, result;
result = {
top: top
};
tuple = [ top, result, 'top' ];
worklist = [ tuple ];
leavelist = [ tuple ];
function notify(v) {
ret = v;
}
while (worklist.length) {
tuple = worklist.pop();
if (tuple === marker) {
tuple = leavelist.pop();
ret = undefined;
if (visitor.leave) {
node = tuple[0];
target = visitor.leave(tuple[0], leavelist[leavelist.length - 1][0], notify);
if (target !== undefined) {
node = target;
}
tuple[1][tuple[2]] = node;
}
if (ret === VisitorOption.Break) {
return result.top;
}
} else if (tuple[0]) {
ret = undefined;
node = tuple[0];
nodeType = node.type;
if (wrappers.hasOwnProperty(nodeType)) {
tuple[0] = node = node.node;
nodeType = wrappers[nodeType];
}
if (visitor.enter) {
target = visitor.enter(tuple[0], leavelist[leavelist.length - 1][0], notify);
if (target !== undefined) {
node = target;
}
tuple[1][tuple[2]] = node;
tuple[0] = node;
}
if (ret === VisitorOption.Break) {
return result.top;
}
if (tuple[0]) {
worklist.push(marker);
leavelist.push(tuple);
if (ret !== VisitorOption.Skip) {
candidates = VisitorKeys[nodeType];
current = candidates.length;
while ((current -= 1) >= 0) {
candidate = node[candidates[current]];
if (candidate) {
if (isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (candidate[current2]) {
if(nodeType === Syntax.ObjectExpression && 'properties' === candidates[current] && null == candidates[current].type) {
worklist.push([{type: 'PropertyWrapper', node: candidate[current2]}, candidate, current2]);
} else {
worklist.push([candidate[current2], candidate, current2]);
}
}
}
} else {
worklist.push([candidate, node, candidates[current]]);
}
}
}
}
}
}
}
return result.top;
}
return { Syntax: Syntax,
traverse: traverse,
replace: replace,
VisitorKeys: VisitorKeys,
VisitorOption: VisitorOption };
});
// This file contains a modified version of the Acorn parser, set up
// for easy use with Angular, cut down to parse only expressions, and
// supporting some extensions to normal JavaScript expression syntax.
//
// ORIGINAL LICENSE COMMENT:
//
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
//
// Acorn was written by Marijn Haverbeke and released under an MIT
// license. The Unicode regexps (for identifiers and whitespace) were
// taken from [Esprima](http://esprima.org) by Ariya Hidayat.
//
// Git repositories for Acorn are available at
//
// http://marijnhaverbeke.nl/git/acorn
// https://github.com/marijnh/acorn.git
//
// Please use the [github bug tracker][ghbt] to report issues.
//
// [ghbt]: https://github.com/marijnh/acorn/issues
radian.factory('radianEval',
['$interpolate', 'plotLib', 'radianParse', 'estraverse', 'genPalFn',
function($interpolate, plotLib, radianParse, estraverse, genPalFn)
{
// Top level JavaScript names that we don't want to treat as free
// variables in Radian expressions.
var excnames = ['Arguments', 'Array', 'Boolean', 'Date', 'Error', 'EvalError',
'Function', 'Global', 'JSON', 'Math', 'Number', 'Object',
'RangeError', 'ReferenceError', 'RegExp', 'String',
'SyntaxError', 'TypeError', 'URIError'];
// We need to be able to call this recursively, so give it a name
// here.
var radianEval = function(scope, inexpr, returnfvs, skiperrors) {
// Pass-through anything that isn't in [[ ]] brackets.
if (typeof inexpr != "string" ||
inexpr.substr(0,2) != '[[' && inexpr.substr(-2) != ']]') {
var retexpr = inexpr;
if (typeof inexpr == "string") retexpr = $interpolate(inexpr)(scope);
return returnfvs ? [retexpr, []] : retexpr;
}
var expr = inexpr.substr(2, inexpr.length-4);
if (expr == "") return returnfvs ? [0, []] : 0;
// Parse data path as (slightly enhanced) JavaScript.
var astorig = radianParse(expr);
estraverse.traverse(astorig, { leave: function(n) {
delete n.start; delete n.end;
} });
// Process palette and interpolator definitions into named
// functions.
var ast = estraverse.replace(astorig, { enter: function(n) {
if (n.type == "PaletteExpression")
return { type: "MemberExpression",
object: { type: "Identifier", name: "rad$$pal" },
property: { type: "Identifier", name: genPalFn(n.palette) } };
else return n;
}});
// Determine metadata key, which is only possible for simple
// applications of member access and plucking. (For example, for
// an expression of the form "vic2012#tmp", the metadata key is
// "tmp"; for the expression "vic2012#date#doy", the metadata key
// is "doy").
var metadatakey = null, dataset = null;
estraverse.traverse(ast, { enter: function(node) {
if (node.type != "PluckExpression" && node.type != "MemberExpression")
return estraverse.VisitorOption.Skip;
else if (node.property.type == "Identifier") {
metadatakey = node.property.name;
var o = node.object;
while (o.type != "Identifier" && o.hasOwnProperty("object"))
o = o.object;
if (o.hasOwnProperty("name")) dataset = o.name;
return estraverse.VisitorOption.Break;
}
}});
// Find free variables in JS expression for later processing.
var exc = { }, excstack = [ ], fvs = { };
excnames.forEach(function(n) { exc[n] = 1; });
Object.keys(plotLib).forEach(function(k) { exc[k] = 1; });
estraverse.traverse(ast, {
enter: function(v, w) {
switch (v.type) {
case "FunctionExpression":
// When we enter a function expression, we need to capture
// the parameter names so that we don't record them as free
// variables. To deal with name shadowing, we use an
// integer counter for names excluded from consideration as
// free variables, rather than a simple boolean flag.
excstack.push(v.params.map(function(p) { return p.name; }));
v.params.forEach(function(p) {
if (exc[p.name]) ++exc[p.name]; else exc[p.name] = 1;
});
break;
case "Identifier":
// We have a free variable, so record it.
if (v.name != 'scope' && !exc[v.name]) {
var free = true;
if (w &&
(((w.type == "MemberExpression" ||
w.type == "PluckExpression") &&
v == w.property && !w.computed) ||
(!w.hasOwnProperty("type") &&
w.hasOwnProperty("key") && v == w.key)))
free = false;
if (free) fvs[v.name] = 1;
}
}
},
leave: function(v) {
if (v.type == "FunctionExpression")
// Clear function parameters from our exclude stack as we
// leave the function expression.
excstack.pop().forEach(function(n) {
if (--exc[n] == 0) delete exc[n];
});
}
});
// Vectorise arithmetic expressions.
var astrepl = estraverse.replace(ast, {
leave: function(n) {
if (n.type == "BinaryExpression") {
var fn = "";
switch (n.operator) {
case "+": fn = "rad$$add"; break;
case "-": fn = "rad$$sub"; break;
case "*": fn = "rad$$mul"; break;
case "/": fn = "rad$$div"; break;
case "**": fn = "rad$$pow"; break;
}
return !fn ? n : {
"type":"CallExpression",
"callee":{ "type":"Identifier","name":fn },
"arguments": [n.left, n.right] };
} else if (n.type == "UnaryExpression" && n.operator == "-") {
return {
"type":"CallExpression",
"callee":{ "type":"Identifier","name":"rad$$neg" },
"arguments": [n.argument] };
} else
return n;
}
});
// Pluck expression transformations:
//
// a#id -> lib.rad$$pluck("a", "id")
// a#id(c) -> a.map(function($$x) { return $$x.id(c); })
// a#n -> a.map(function($$x) { return $$x[n]; })
// a#(expr) -> a.map(function($$x) { return $$x[expr]; })
//
astrepl = estraverse.replace(astrepl, {
enter: function(n) {
if (n.type == "CallExpression" && n.callee.type == "PluckExpression") {
return{
type:"CallExpression",
callee:{type:"MemberExpression", object:n.callee.object,
property:{type:"Identifier", name:"map"},
computed:false},
arguments:
[{type:"FunctionExpression",
id:null, params:[{type:"Identifier", name:"$$x"}],
body:{
type:"BlockStatement",
body:[{
type:"ReturnStatement",
argument:{type:"CallExpression",
callee:{type:"MemberExpression",
object:{type:"Identifier", name:"$$x"},
property:n.callee.property,
computed:n.callee.computed},
arguments:n.arguments}
}]
}
}]
};
} else return n;
},
leave: function(n) {
if (n.type == "PluckExpression") {
if (n.property.type == "Identifier" && !n.computed) {
return {
type:"CallExpression",
callee:{ type:"Identifier", name:"rad$$pluck" },
arguments:
[ n.object,
{ type: "Literal",
value: n.property.name,
raw: "'" + n.property.name + "'" }]};
} else
return {
type:"CallExpression",
callee:{ type:"MemberExpression", object:n.object,
property:{ type:"Identifier", name:"map" },
computed:false },
arguments:
[{ type:"FunctionExpression",
id:null, params:[{ type:"Identifier", name:"$$x"}],
body:{
type:"BlockStatement",
body:[{ type:"ReturnStatement",
argument:{ type:"MemberExpression",
object:{ type:"Identifier", name:"$$x" },
property:n.property,
computed:n.computed}
}]
}
}]
};
}}});
// Replace free variables in JS expression by calls to
// "scope.$eval". We do things this way rather than using
// Angular's "scope.$eval" on the whole JS expression because the
// Angular expression parser only deals with a relatively small
// subset of JS (no anonymous functions, for instance).
astrepl = estraverse.replace(astrepl, {
enter: function(v, w) {
switch (v.type) {
case "FunctionExpression":
// When we enter a function expression, we need to capture
// the parameter names so that we don't record them as free
// variables. To deal with name shadowing, we use an
// integer counter for names excluded from consideration as
// free variables, rather than a simple boolean flag.
excstack.push(v.params.map(function(p) { return p.name; }));
v.params.forEach(function(p) {
if (exc[p.name]) ++exc[p.name]; else exc[p.name] = 1;
});
break;
case "Identifier":
if (!(w.hasOwnProperty('key') && v == w.key) &&
!exc[v.name] && fvs[v.name]) {
// We have a free variable, so replace the reference to it
// with a call to 'scope.$eval'.
return {
type: "CallExpression",
callee: { type: "MemberExpression",
object: { type: "Identifier", name: "scope" },
property: { type: "Identifier", name: "$eval" },
computed: false },
arguments: [{ type: "Literal", value: v.name,
raw:"'" + v.name + "'" }]
};
}
}
return v;
},
leave: function(v) {
if (v.type == "FunctionExpression")
// Clear function parameters from our exclude stack as we
// leave the function expression.
excstack.pop().forEach(function(n) {
if (--exc[n] == 0) delete exc[n];
});
return v;
}
});
// Generate JS code suitable for accessing data.
var access = escodegen.generate(astrepl);
var ret = [];
try {
// Bring plot function library names into scope.
with (plotLib) {
eval("ret = " + access);
}
} catch (e) {
if (!skiperrors)
throw Error("radianEval failed on '" + expr + "' -- " + e.message);
}
if (ret && dataset && metadatakey) {
if (scope[dataset] && scope[dataset].metadata &&
scope[dataset].metadata[metadatakey])
ret.metadata = scope[dataset].metadata[metadatakey];
}
return returnfvs ? [ret, Object.keys(fvs)] : ret;
};
return radianEval;
}]);
radian.factory('radianParse', function()
{
'use strict';
// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
// returns an abstract syntax tree as specified by [Mozilla parser
// API][api], with the caveat that the SpiderMonkey-specific syntax
// (`let`, `yield`, inline XML, etc) is not recognized.
//
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
var input, inputLen;
var mainfn = function(inpt) {
input = String(inpt); inputLen = input.length;
initTokenState();
return parseTopLevel();
};
// The `getLineInfo` function is mostly useful when the
// `locations` option is off (for performance reasons) and you
// want to find the line/column position for a given character
// offset. `input` should be the code string that the offset refers
// into.
var getLineInfo = function(input, offset) {
for (var line = 1, cur = 0;;) {
lineBreak.lastIndex = cur;
var match = lineBreak.exec(input);
if (match && match.index < offset) {
++line;
cur = match.index + match[0].length;
} else break;
}
return {line: line, column: offset - cur};
};
// Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenize` export provides an interface to the tokenizer.
// Because the tokenizer is optimized for being efficiently used by
// the Acorn parser itself, this interface is somewhat crude and not
// very modular. Performing another parse or call to `tokenize` will
// reset the internal state, and invalidate existing tokenizers.
function tokenize(inpt, opts) {
input = String(inpt); inputLen = input.length;
initTokenState();
var t = {};
function getToken(forceRegexp) {
readToken(forceRegexp);
t.start = tokStart; t.end = tokEnd;
t.type = tokType; t.value = tokVal;
return t;
}
getToken.jumpTo = function(pos, reAllowed) {
tokPos = pos;
var ch = input.charAt(pos - 1);
tokRegexpAllowed = reAllowed;
skipSpace();
};
return getToken;
};
// State is kept in (closure-)global variables. We already saw the
// `input`, and `inputLen` variables above.
// The current position of the tokenizer in the input.
var tokPos;
// The start and end offsets of the current token.
var tokStart, tokEnd;
// The type and value of the current token. Token types are objects,
// named by variables against which they can be compared, and
// holding properties that describe them (indicating, for example,
// the precedence of an infix operator, and the original name of a
// keyword token). The kind of value that's held in `tokVal` depends
// on the type of the token. For literals, it is the literal value,
// for operators, the operator name, and so on.
var tokType, tokVal;
// Interal state for the tokenizer. To distinguish between division
// operators and regular expressions, it remembers whether the last
// token was one that is allowed to be followed by an expression.
// (If it is, a slash is probably a regexp, if it isn't it's a
// division operator. See the `parseStatement` function for a
// caveat.)
var tokRegexpAllowed;
// These store the position of the previous token, which is useful
// when finishing a node and assigning its `end` position.
var lastStart, lastEnd, lastEndLoc;
// This is the parser's state. `inFunction` is used to reject
// `return` statements outside of functions, `labels` to verify that
// `break` and `continue` have somewhere to jump to, and `strict`
// indicates whether strict mode is on.
var inFunction, labels, strict;
// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.
function raise(pos, message) {
var loc = getLineInfo(input, pos);
message += " (" + loc.line + ":" + loc.column + ")";
var err = new SyntaxError(message);
err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
throw err;
}
// ## Token types
// The assignment of fine-grained, information-carrying type objects
// allows the tokenizer to store the information it has about a
// token in a way that is very cheap for the parser to look up.
// All token type variables start with an underscore, to make them
// easy to recognize.
// These are the general types. The `type` property is only used to
// make them recognizeable when debugging.
var _num = {type: "num"}, _regexp = {type: "regexp"};
var _string = {type: "string"}, _name = {type: "name"};
var _colour = {type: "colour"}, _eof = {type: "eof"};
// Keyword tokens. The `keyword` property (also used in keyword-like
// operators) indicates that the token originated from an
// identifier-like word, which is used when parsing property names.
//
// The `beforeExpr` property is used to disambiguate between regular
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.
var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true};
var _catch = {keyword: "catch"}, _continue = {keyword: "continue"};
var _debugger = {keyword: "debugger"}, _default = {keyword: "default"};
var _do = {keyword: "do", isLoop: true};
var _else = {keyword: "else", beforeExpr: true};
var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true};
var _function = {keyword: "function"}, _if = {keyword: "if"};
var _return = {keyword: "return", beforeExpr: true};
var _switch = {keyword: "switch"};
var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"};
var _var = {keyword: "var"}, _while = {keyword: "while", isLoop: true};
var _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true};
var _this = {keyword: "this"};
var _palette = {keyword: "@P"}, _interpolator = {keyword: "@I"};
// The keywords that denote values.
var _null = {keyword: "null", atomValue: null};
var _true = {keyword: "true", atomValue: true};
var _false = {keyword: "false", atomValue: false};
// Some keywords are treated as regular operators. `in` sometimes
// (when parsing `for`) needs to be tested against specifically, so
// we assign a variable name to it for quick comparing.
var _in = {keyword: "in", binop: 7, beforeExpr: true};
// Map keyword names to token types.
var keywordTypes =
{"break": _break, "case": _case, "catch": _catch, "continue": _continue,
"debugger": _debugger, "default": _default, "do": _do, "else": _else,
"finally": _finally, "for": _for, "function": _function, "if": _if,
"return": _return, "switch": _switch, "throw": _throw, "try": _try,
"var": _var, "while": _while, "with": _with, "null": _null, "true": _true,
"false": _false, "new": _new, "in": _in,
"instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true},
"this": _this, "@P": _palette, "@I": _interpolator,
"typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
"void": {keyword: "void", prefix: true, beforeExpr: true},
"delete": {keyword: "delete", prefix: true, beforeExpr: true}};
// Punctuation token types. Again, the `type` property is purely for
// debugging.
var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"};
var _braceL = {type: "{", beforeExpr: true}, _braceR = {type: "}"};
var _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
var _comma = {type: ",", beforeExpr: true};
var _semi = {type: ";", beforeExpr: true};
var _colon = {type: ":", beforeExpr: true};
var _dot = {type: "."}, _question = {type: "?", beforeExpr: true};
var _hash = {type: "#"};
// Operators. These carry several kinds of properties to help the
// parser use them properly (the presence of these properties is
// what categorizes them as operators).
//
// `binop`, when present, specifies that this operator is a binary
// operator, and will refer to its precedence.
//
// `prefix` and `postfix` mark the operator as a prefix or postfix
// unary operator. `isUpdate` specifies that the node produced by
// the operator should be of type UpdateExpression rather than
// simply UnaryExpression (`++` and `--`).
//
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
// binary operators with a very low precedence, that should result
// in AssignmentExpression nodes.
var _slash = {binop: 10, beforeExpr: true};
var _eq = {isAssign: true, beforeExpr: true};
var _assign = {isAssign: true, beforeExpr: true};
var _plusmin = {binop: 9, prefix: true, beforeExpr: true};
var _incdec = {postfix: true, prefix: true, isUpdate: true};
var _prefix = {prefix: true, beforeExpr: true};
var _bin1 = {binop: 1, beforeExpr: true};
var _bin2 = {binop: 2, beforeExpr: true};
var _bin3 = {binop: 3, beforeExpr: true};
var _bin4 = {binop: 4, beforeExpr: true};
var _bin5 = {binop: 5, beforeExpr: true};
var _bin6 = {binop: 6, beforeExpr: true};
var _bin7 = {binop: 7, beforeExpr: true};
var _bin8 = {binop: 8, beforeExpr: true};
var _bin10 = {binop: 10, beforeExpr: true};
var _bin11 = {binop: 11, beforeExpr: true};
// Provide access to the token types for external users of the
// tokenizer.
var tokTypes =
{bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi,
colon: _colon, dot: _dot, question: _question, slash: _slash, eq: _eq,
name: _name, eof: _eof,
num: _num, regexp: _regexp, string: _string, hash: _hash};
for (var kw in keywordTypes) tokTypes[kw] = keywordTypes[kw];
// This is a trick taken from Esprima. It turns out that, on
// non-Chrome browsers, to check whether a string is in a set, a
// predicate containing a big ugly `switch` statement is faster than
// a regular expression, and on Chrome the two are about on par.
// This function uses `eval` (non-lexical) to produce such a
// predicate from a space-separated string of words.
//
// It starts by sorting the words by length.
function makePredicate(words) {
words = words.split(" ");
var f = "", cats = [], skip;
// out: for (var i = 0; i < words.length; ++i) {
for (var i = 0; i < words.length; ++i) {
skip = false;
for (var j = 0; j < cats.length; ++j)
if (cats[j][0].length == words[i].length) {
cats[j].push(words[i]);
skip = true;
break;
// continue out;
}
if (!skip) cats.push([words[i]]);
skip = false;
}
function compareTo(arr) {
if (arr.length == 1)
return f += "return str === " + JSON.stringify(arr[0]) + ";";
f += "switch(str){";
for (var i = 0; i < arr.length; ++i)
f += "case " + JSON.stringify(arr[i]) + ":";
f += "return true}return false;";
}
// When there are more than three length categories, an outer
// switch first dispatches on the lengths, to save on comparisons.
if (cats.length > 3) {
cats.sort(function(a, b) {return b.length - a.length;});
f += "switch(str.length){";
for (var i = 0; i < cats.length; ++i) {
var cat = cats[i];
f += "case " + cat[0].length + ":";
compareTo(cat);
}
f += "}";
// Otherwise, simply generate a flat `switch` statement.
} else {
compareTo(words);
}
return new Function("str", f);
}
// ECMAScript 5 reserved words.
var isReservedWord5 =
makePredicate("class enum extends super const export import");
// The additional reserved words in strict mode.
var isStrictReservedWord =
makePredicate("implements interface let package private " +
"protected public static yield");
// The forbidden variable names in strict mode.
var isStrictBadIdWord = makePredicate("eval arguments");
// And the keywords.
var isKeyword =
makePredicate("break case catch continue debugger default do " +
"else finally for function if return switch throw try " +
"var while with null true false instanceof typeof void " +
"delete new in this");
// ## Character categories
// Big ugly regular expressions that match characters in the
// whitespace, identifier, and identifier-start categories. These
// are only applied when a character is found to actually have a
// code point above 128.
var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/;
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
var nonASCIIidentifierChars = "\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
// Whether a single character denotes a newline.
var newline = /[\n\r\u2028\u2029]/;
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.
var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
// Test whether a given character code starts an identifier.
function isIdentifierStart(code) {
if (code < 65) return code === 36;
if (code < 91) return true;
if (code < 97) return code === 95;
if (code < 123)return true;
return code >= 0xaa &&
nonASCIIidentifierStart.test(String.fromCharCode(code));
}
// Test whether a given character is part of an identifier.
function isIdentifierChar(code) {
if (code < 48) return code === 36;
if (code < 58) return true;
if (code < 65) return false;
if (code < 91) return true;
if (code < 97) return code === 95;
if (code < 123)return true;
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
}
// ## Tokenizer
// Reset the token state. Used at the start of a parse.
function initTokenState() {
tokPos = 0;
tokRegexpAllowed = true;
skipSpace();
}
// Called at the end of every token. Sets `tokEnd`, `tokVal`, and
// `tokRegexpAllowed`, and skips the space after the token, so that
// the next one's `tokStart` will point at the right position.
function finishToken(type, val) {
tokEnd = tokPos;
tokType = type;
skipSpace();
tokVal = val;
tokRegexpAllowed = type.beforeExpr;
}
function skipBlockComment() {
var end = input.indexOf("*/", tokPos += 2);
if (end === -1) raise(tokPos - 2, "Unterminated comment");
tokPos = end + 2;
}
function skipLineComment() {
var ch = input.charCodeAt(tokPos+=2);
while (tokPos < inputLen && ch !== 10 &&
ch !== 13 && ch !== 8232 && ch !== 8329) {
++tokPos;
ch = input.charCodeAt(tokPos);
}
}
// Called at the start of the parse and after every token. Skips
// whitespace and comments, and.
function skipSpace() {
while (tokPos < inputLen) {
var ch = input.charCodeAt(tokPos);
if (ch === 32) { // ' '
++tokPos;
} else if(ch === 13) {
++tokPos;
var next = input.charCodeAt(tokPos);
if(next === 10) {
++tokPos;
}
} else if (ch === 10) {
++tokPos;
} else if(ch < 14 && ch > 8) {
++tokPos;
} else if (ch === 47) { // '/'
var next = input.charCodeAt(tokPos+1);
if (next === 42) { // '*'
skipBlockComment();
} else if (next === 47) { // '/'
skipLineComment();
} else break;
} else if ((ch < 14 && ch > 8) ||
ch === 32 || ch === 160) { // ' ', '\xa0'
++tokPos;
} else if (ch >= 5760 &&
nonASCIIwhitespace.test(String.fromCharCode(ch))) {
++tokPos;
} else {
break;
}
}
}
// ### Token reading
// This is the function that is called to fetch the next token. It
// is somewhat obscure, because it works in character codes rather
// than characters, and because operator parsing has been inlined
// into it.
//
// All in the name of speed.
//
// The `forceRegexp` parameter is used in the one case where the
// `tokRegexpAllowed` trick does not work. See `parseStatement`.
function readToken_dot() {
var next = input.charCodeAt(tokPos+1);
if (next >= 48 && next <= 57) return readNumber(true);
++tokPos;
return finishToken(_dot);
}
function readToken_slash() { // '/'
var next = input.charCodeAt(tokPos+1);
if (tokRegexpAllowed) {++tokPos; return readRegexp();}
if (next === 61) return finishOp(_assign, 2);
return finishOp(_slash, 1);
}
function readToken_mult_modulo() { // '%', '*' and '**'
var next = input.charCodeAt(tokPos+1);
if (next === 61) return finishOp(_assign, 2);
if (next === 42) {
var next2 = input.charCodeAt(tokPos+2);
if (next === 61) return finishOp(_assign, 3);
return finishOp(_bin11, 2);
}
return finishOp(_bin10, 1);
}
function readToken_pipe_amp(code) { // '|&'
var next = input.charCodeAt(tokPos+1);
if (next === code) return finishOp(code === 124 ? _bin1 : _bin2, 2);
if (next === 61) return finishOp(_assign, 2);
return finishOp(code === 124 ? _bin3 : _bin5, 1);
}
function readToken_caret() { // '^'
var next = input.charCodeAt(tokPos+1);
if (next === 61) return finishOp(_assign, 2);
return finishOp(_bin4, 1);
}
function readToken_plus_min(code) { // '+-'
var next = input.charCodeAt(tokPos+1);
if (next === code) return finishOp(_incdec, 2);
if (next === 61) return finishOp(_assign, 2);
return finishOp(_plusmin, 1);
}
function readToken_lt_gt(code) { // '<>'
var next = input.charCodeAt(tokPos+1);
var size = 1;
if (next === code) {
size = code === 62 && input.charCodeAt(tokPos+2) === 62 ? 3 : 2;
if (input.charCodeAt(tokPos + size) === 61)
return finishOp(_assign, size + 1);
return finishOp(_bin8, size);
}
if (next === 61)
size = input.charCodeAt(tokPos+2) === 61 ? 3 : 2;
return finishOp(_bin7, size);
}
function readToken_eq_excl(code) { // '=!'
var next = input.charCodeAt(tokPos+1);
if (next === 61)
return finishOp(_bin6, input.charCodeAt(tokPos+2) === 61 ? 3 : 2);
return finishOp(code === 61 ? _eq : _prefix, 1);
}
function readToken_pal_interp() { // '@'
var next = input.charCodeAt(tokPos+1);
if (next == 80) return finishOp(_palette, 2); // 'P'
else if (next == 73) return finishOp(_interpolator, 2); // 'I'
else raise("Invalid palette token sequence");
}
function readToken_colour() { // '#'
function ishex(c) {
return c>='0' && c<='9' || c>='A' && c<='F' || c>='a' && c<='f';
};
++tokPos;
var n = 0;
for (var i = tokPos; ishex(input.charAt(i)) && n < 6; ++i) ++n;
var val;
if (n == 6) { val = input.substr(tokPos, 6); tokPos += 6; }
else if (n == 3) { val = input.substr(tokPos, 3); tokPos += 3; }
else raise("Invalid colour constant");
var type = _colour;
return finishToken(type, val);
}
function getTokenFromCode(code, doColour) {
switch(code) {
// The interpretation of a dot depends on whether it is followed
// by a digit.
case 46: // '.'
return readToken_dot();
// Punctuation tokens.
case 35:
if (doColour) return readToken_colour();
else { ++tokPos; return finishToken(_hash); }
case 40: ++tokPos; return finishToken(_parenL);
case 41: ++tokPos; return finishToken(_parenR);
case 59: ++tokPos; return finishToken(_semi);
case 44: ++tokPos; return finishToken(_comma);
case 91: ++tokPos; return finishToken(_bracketL);
case 93: ++tokPos; return finishToken(_bracketR);
case 123: ++tokPos; return finishToken(_braceL);
case 125: ++tokPos; return finishToken(_braceR);
case 58: ++tokPos; return finishToken(_colon);
case 63: ++tokPos; return finishToken(_question);
// '0x' is a hexadecimal number.
case 48: // '0'
var next = input.charCodeAt(tokPos+1);
if (next === 120 || next === 88) return readHexNumber();
// Anything else beginning with a digit is an integer, octal
// number, or float.
case 49: case 50: case 51: case 52: case 53:
case 54: case 55: case 56: case 57: // 1-9
return readNumber(false);
// Quotes produce strings.
case 34: case 39: // '"', "'"
return readString(code);
// Operators are parsed inline in tiny state machines. '=' (61) is
// often referred to. `finishOp` simply skips the amount of
// characters it is given as second argument, and returns a token
// of the type given by its first argument.
case 47: // '/'
return readToken_slash(code);
case 37: case 42: // '%*'
return readToken_mult_modulo();
case 124: case 38: // '|&'
return readToken_pipe_amp(code);
case 94: // '^'
return readToken_caret();
case 43: case 45: // '+-'
return readToken_plus_min(code);
case 60: case 62: // '<>'
return readToken_lt_gt(code);
case 61: case 33: // '=!'
return readToken_eq_excl(code);
case 126: // '~'
return finishOp(_prefix, 1);
case 64: // '@'
return readToken_pal_interp(code);
}
return false;
}
function readToken(forceRegexp, doColour) {
if (doColour) --tokPos;
tokStart = tokPos;
if (forceRegexp) return readRegexp();
if (tokPos >= inputLen) return finishToken(_eof);
var code = input.charCodeAt(tokPos);
// Identifier or keyword. '\uXXXX' sequences are allowed in
// identifiers, so '\' also dispatches to that.
if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
var tok = getTokenFromCode(code, doColour);
if (tok === false) {
// If we are here, we either found a non-ASCII identifier
// character, or something that's entirely disallowed.
var ch = String.fromCharCode(code);
if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord();
raise(tokPos, "Unexpected character '" + ch + "'");
}
return tok;
}
function finishOp(type, size) {
var str = input.slice(tokPos, tokPos + size);
tokPos += size;
finishToken(type, str);
}
// Parse a regular expression. Some context-awareness is necessary,
// since a '/' inside a '[]' set does not end the expression.
function readRegexp() {
var content = "", escaped, inClass, start = tokPos;
for (;;) {
if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
var ch = input.charAt(tokPos);
if (newline.test(ch)) raise(start, "Unterminated regular expression");
if (!escaped) {
if (ch === "[") inClass = true;
else if (ch === "]" && inClass) inClass = false;
else if (ch === "/" && !inClass) break;
escaped = ch === "\\";
} else escaped = false;
++tokPos;
}
var content = input.slice(start, tokPos);
++tokPos;
// Need to use `readWord1` because '\uXXXX' sequences are allowed
// here (don't ask).
var mods = readWord1();
if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regexp flag");
return finishToken(_regexp, new RegExp(content, mods));
}
// Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits.
function readInt(radix, len) {
var start = tokPos, total = 0;
for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
var code = input.charCodeAt(tokPos), val;
if (code >= 97) val = code - 97 + 10; // a
else if (code >= 65) val = code - 65 + 10; // A
else if (code >= 48 && code <= 57) val = code - 48; // 0-9
else val = Infinity;
if (val >= radix) break;
++tokPos;
total = total * radix + val;
}
if (tokPos === start || len != null && tokPos - start !== len) return null;
return total;
}
function readHexNumber() {
tokPos += 2; // 0x
var val = readInt(16);
if (val == null) raise(tokStart + 2, "Expected hexadecimal number");
if (isIdentifierStart(input.charCodeAt(tokPos)))
raise(tokPos, "Identifier directly after number");
return finishToken(_num, val);
}
// Read an integer, octal integer, or floating-point number.
function readNumber(startsWithDot) {
var start = tokPos, isFloat = false;
var octal = input.charCodeAt(tokPos) === 48;
if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");
if (input.charCodeAt(tokPos) === 46) {
++tokPos;
readInt(10);
isFloat = true;
}
var next = input.charCodeAt(tokPos);
if (next === 69 || next === 101) { // 'eE'
next = input.charCodeAt(++tokPos);
if (next === 43 || next === 45) ++tokPos; // '+-'
if (readInt(10) === null) raise(start, "Invalid number")
isFloat = true;
}
if (isIdentifierStart(input.charCodeAt(tokPos)))
raise(tokPos, "Identifier directly after number");
var str = input.slice(start, tokPos), val;
if (isFloat) val = parseFloat(str);
else if (!octal || str.length === 1) val = parseInt(str, 10);
else if (/[89]/.test(str) || strict) raise(start, "Invalid number");
else val = parseInt(str, 8);
return finishToken(_num, val);
}
// Read a string value, interpreting backslash-escapes.
var rs_str = [];
function readString(quote) {
tokPos++;
rs_str.length = 0;
for (;;) {
if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
var ch = input.charCodeAt(tokPos);
if (ch === quote) {
++tokPos;
return finishToken(_string, String.fromCharCode.apply(null, rs_str));
}
if (ch === 92) { // '\'
ch = input.charCodeAt(++tokPos);
var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
if (octal) octal = octal[0];
while (octal && parseInt(octal, 8) > 255)
octal = octal.slice(0, octal.length - 1);
if (octal === "0") octal = null;
++tokPos;
if (octal) {
if (strict) raise(tokPos - 2, "Octal literal in strict mode");
rs_str.push(parseInt(octal, 8));
tokPos += octal.length - 1;
} else {
switch (ch) {
case 110: rs_str.push(10); break; // 'n' -> '\n'
case 114: rs_str.push(13); break; // 'r' -> '\r'
case 120: rs_str.push(readHexChar(2)); break; // 'x'
case 117: rs_str.push(readHexChar(4)); break; // 'u'
case 85: rs_str.push(readHexChar(8)); break; // 'U'
case 116: rs_str.push(9); break; // 't' -> '\t'
case 98: rs_str.push(8); break; // 'b' -> '\b'
case 118: rs_str.push(11); break; // 'v' -> '\u000b'
case 102: rs_str.push(12); break; // 'f' -> '\f'
case 48: rs_str.push(0); break; // 0 -> '\0'
case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
case 10: // ' \n'
break;
default: rs_str.push(ch); break;
}
}
} else {
if (ch === 13 || ch === 10 || ch === 8232 || ch === 8329)
raise(tokStart, "Unterminated string constant");
rs_str.push(ch); // '\'
++tokPos;
}
}
}
// Used to read character escape sequences ('\x', '\u', '\U').
function readHexChar(len) {
var n = readInt(16, len);
if (n === null) raise(tokStart, "Bad character escape sequence");
return n;
}
// Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
var containsEsc;
// Read an identifier, and return it as a string. Sets `containsEsc`
// to whether the word contained a '\u' escape.
//
// Only builds up the word character-by-character when it actually
// containeds an escape, as a micro-optimization.
function readWord1() {
containsEsc = false;
var word, first = true, start = tokPos;
for (;;) {
var ch = input.charCodeAt(tokPos);
if (isIdentifierChar(ch)) {
if (containsEsc) word += input.charAt(tokPos);
++tokPos;
} else if (ch === 92) { // "\"
if (!containsEsc) word = input.slice(start, tokPos);
containsEsc = true;
if (input.charCodeAt(++tokPos) != 117) // "u"
raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
++tokPos;
var esc = readHexChar(4);
var escStr = String.fromCharCode(esc);
if (!escStr) raise(tokPos - 1, "Invalid Unicode escape");
if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
raise(tokPos - 4, "Invalid Unicode escape");
word += escStr;
} else {
break;
}
first = false;
}
return containsEsc ? word : input.slice(start, tokPos);
}
// Read an identifier or keyword token. Will check for reserved
// words when necessary.
function readWord() {
var word = readWord1();
var type = _name;
if (!containsEsc) {
if (isKeyword(word)) type = keywordTypes[word];
else if (strict && isStrictReservedWord(word))
raise(tokStart, "The keyword '" + word + "' is reserved");
}
return finishToken(type, word);
}
// ## Parser
// A recursive descent parser operates by defining functions for all
// syntactic elements, and recursively calling those, each function
// advancing the input stream and returning an AST node. Precedence
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
// instead of `(!x)[1]` is handled by the fact that the parser
// function that parses unary prefix operators is called first, and
// in turn calls the function that parses `[]` subscripts — that
// way, it'll receive the node for `x[1]` already parsed, and wraps
// *that* in the unary operator node.
//
// Acorn uses an [operator precedence parser][opp] to handle binary
// operator precedence, because it is much more compact than using
// the technique outlined above, which uses different, nesting
// functions to specify precedence, for all of the ten binary
// precedence levels that JavaScript defines.
//
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
// ### Parser utilities
// Continue to the next token.
function next() {
lastStart = tokStart;
lastEnd = tokEnd;
readToken();
}
// Enter strict mode. Re-reads the next token to please pedantic
// tests ("use strict"; 010; -- should fail).
function setStrict(strct) {
strict = strct;
tokPos = lastEnd;
skipSpace();
readToken();
}
// Start an AST node, attaching a start offset.
function node_t() {
this.type = null;
this.start = tokStart;
this.end = null;
}
function startNode() { return new node_t(); }
// Start a node whose start offset information should be based on
// the start of another node. For example, a binary operator node is
// only started after its left-hand side has already been parsed.
function startNodeFrom(other) {
var node = new node_t();
node.start = other.start;
return node;
}
// Finish an AST node, adding `type` and `end` properties.
function finishNode(node, type) {
node.type = type;
node.end = lastEnd;
return node;
}
// Test whether a statement node is the string literal `"use strict"`.
function isUseStrict(stmt) {
return stmt.type === "ExpressionStatement" &&
stmt.expression.type === "Literal" &&
stmt.expression.value === "use strict";
}
// Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.
function eat(type) {
if (tokType === type) {
next();
return true;
}
}
// Test whether a semicolon can be inserted at the current position.
function canInsertSemicolon() {
return (tokType === _eof || tokType === _braceR ||
newline.test(input.slice(lastEnd, tokStart)));
}
// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.
function semicolon() {
if (!eat(_semi) && !canInsertSemicolon()) unexpected();
}
// Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.
function expect(type) {
if (tokType === type) next();
else unexpected();
}
// Raise an unexpected token error.
function unexpected() {
raise(tokStart, "Unexpected token");
}
// Verify that a node is an lval — something that can be assigned
// to.
function checkLVal(expr) {
if (expr.type !== "Identifier" && expr.type !== "MemberExpression")
raise(expr.start, "Assigning to rvalue");
if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name))
raise(expr.start, "Assigning to " + expr.name + " in strict mode");
}
// ### Top level parsing
// Parse an expression. Initializes the parser, reads a single
// expression and returns it.
function parseTopLevel() {
lastStart = lastEnd = tokPos;
inFunction = strict = null;
labels = [];
readToken();
return parseExpression();
}
var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
// Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
// regular expression literal. This is to handle cases like
// `if (foo) /blah/.exec(foo);`, where looking at the previous token
// does not help.
function parseStatement() {
if (tokType === _slash)
readToken(true);
var starttype = tokType, node = startNode();
// Most types of statements are recognized by the keyword they
// start with. Many are trivial to parse, some require a bit of
// complexity.
switch (starttype) {
case _break: case _continue:
next();
var isBreak = starttype === _break;
if (eat(_semi) || canInsertSemicolon()) node.label = null;
else if (tokType !== _name) unexpected();
else {
node.label = parseIdent();
semicolon();
}
// Verify that there is an actual destination to break or
// continue to.
for (var i = 0; i < labels.length; ++i) {
var lab = labels[i];
if (node.label == null || lab.name === node.label.name) {
if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
if (node.label && isBreak) break;
}
}
if (i === labels.length)
raise(node.start, "Unsyntactic " + starttype.keyword);
return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
case _debugger:
next();
semicolon();
return finishNode(node, "DebuggerStatement");
case _do:
next();
labels.push(loopLabel);
node.body = parseStatement();
labels.pop();
expect(_while);
node.test = parseParenExpression();
semicolon();
return finishNode(node, "DoWhileStatement");
// Disambiguating between a `for` and a `for`/`in` loop is
// non-trivial. Basically, we have to parse the init `var`
// statement or expression, disallowing the `in` operator (see
// the second parameter to `parseExpression`), and then check
// whether the next token is `in`. When there is no init part
// (semicolon immediately after the opening parenthesis), it is
// a regular `for` loop.
case _for:
next();
labels.push(loopLabel);
expect(_parenL);
if (tokType === _semi) return parseFor(node, null);
if (tokType === _var) {
var init = startNode();
next();
parseVar(init, true);
if (init.declarations.length === 1 && eat(_in))
return parseForIn(node, init);
return parseFor(node, init);
}
var init = parseExpression(false, true);
if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}
return parseFor(node, init);
case _function:
next();
return parseFunction(node, true);
case _if:
next();
node.test = parseParenExpression();
node.consequent = parseStatement();
node.alternate = eat(_else) ? parseStatement() : null;
return finishNode(node, "IfStatement");
case _return:
if (!inFunction) raise(tokStart, "'return' outside of function");
next();
// In `return` (and `break`/`continue`), the keywords with
// optional arguments, we eagerly look for a semicolon or the
// possibility to insert one.
if (eat(_semi) || canInsertSemicolon()) node.argument = null;
else { node.argument = parseExpression(); semicolon(); }
return finishNode(node, "ReturnStatement");
case _switch:
next();
node.discriminant = parseParenExpression();
node.cases = [];
expect(_braceL);
labels.push(switchLabel);
// Statements under must be grouped (by label) in SwitchCase
// nodes. `cur` is used to keep the node that we are currently
// adding statements to.
for (var cur, sawDefault; tokType != _braceR;) {
if (tokType === _case || tokType === _default) {
var isCase = tokType === _case;
if (cur) finishNode(cur, "SwitchCase");
node.cases.push(cur = startNode());
cur.consequent = [];
next();
if (isCase) cur.test = parseExpression();
else {
if (sawDefault)
raise(lastStart, "Multiple default clauses"); sawDefault = true;
cur.test = null;
}
expect(_colon);
} else {
if (!cur) unexpected();
cur.consequent.push(parseStatement());
}
}
if (cur) finishNode(cur, "SwitchCase");
next(); // Closing brace
labels.pop();
return finishNode(node, "SwitchStatement");
case _throw:
next();
if (newline.test(input.slice(lastEnd, tokStart)))
raise(lastEnd, "Illegal newline after throw");
node.argument = parseExpression();
semicolon();
return finishNode(node, "ThrowStatement");
case _try:
next();
node.block = parseBlock();
node.handlers = [];
while (tokType === _catch) {
var clause = startNode();
next();
expect(_parenL);
clause.param = parseIdent();
if (strict && isStrictBadIdWord(clause.param.name))
raise(clause.param.start, "Binding " +
clause.param.name + " in strict mode");
expect(_parenR);
clause.guard = null;
clause.body = parseBlock();
node.handlers.push(finishNode(clause, "CatchClause"));
}
node.finalizer = eat(_finally) ? parseBlock() : null;
if (!node.handlers.length && !node.finalizer)
raise(node.start, "Missing catch or finally clause");
return finishNode(node, "TryStatement");
case _var:
next();
node = parseVar(node);
semicolon();
return node;
case _while:
next();
node.test = parseParenExpression();
labels.push(loopLabel);
node.body = parseStatement();
labels.pop();
return finishNode(node, "WhileStatement");
case _with:
if (strict) raise(tokStart, "'with' in strict mode");
next();
node.object = parseParenExpression();
node.body = parseStatement();
return finishNode(node, "WithStatement");
case _braceL:
return parseBlock();
case _semi:
next();
return finishNode(node, "EmptyStatement");
// If the statement does not start with a statement keyword or a
// brace, it's an ExpressionStatement or LabeledStatement. We
// simply start parsing an expression, and afterwards, if the
// next token is a colon and the expression was a simple
// Identifier node, we switch to interpreting it as a label.
default:
var maybeName = tokVal, expr = parseExpression();
if (starttype === _name && expr.type === "Identifier" && eat(_colon)) {
for (var i = 0; i < labels.length; ++i)
if (labels[i].name === maybeName)
raise(expr.start, "Label '" + maybeName + "' is already declared");
var kind = tokType.isLoop ?
"loop" : tokType === _switch ? "switch" : null;
labels.push({name: maybeName, kind: kind});
node.body = parseStatement();
labels.pop();
node.label = expr;
return finishNode(node, "LabeledStatement");
} else {
node.expression = expr;
semicolon();
return finishNode(node, "ExpressionStatement");
}
}
}
// Used for constructs like `switch` and `if` that insist on
// parentheses around their expression.
function parseParenExpression() {
expect(_parenL);
var val = parseExpression();
expect(_parenR);
return val;
}
// Parse a semicolon-enclosed block of statements, handling `"use
// strict"` declarations when `allowStrict` is true (used for
// function bodies).
function parseBlock(allowStrict) {
var node = startNode(), first = true, strict = false, oldStrict;
node.body = [];
expect(_braceL);
while (!eat(_braceR)) {
var stmt = parseStatement();
node.body.push(stmt);
if (first && isUseStrict(stmt)) {
oldStrict = strict;
setStrict(strict = true);
}
first = false
}
if (strict && !oldStrict) setStrict(false);
return finishNode(node, "BlockStatement");
}
// Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.
function parseFor(node, init) {
node.init = init;
expect(_semi);
node.test = tokType === _semi ? null : parseExpression();
expect(_semi);
node.update = tokType === _parenR ? null : parseExpression();
expect(_parenR);
node.body = parseStatement();
labels.pop();
return finishNode(node, "ForStatement");
}
// Parse a `for`/`in` loop.
function parseForIn(node, init) {
node.left = init;
node.right = parseExpression();
expect(_parenR);
node.body = parseStatement();
labels.pop();
return finishNode(node, "ForInStatement");
}
// Parse a list of variable declarations.
function parseVar(node, noIn) {
node.declarations = [];
node.kind = "var";
for (;;) {
var decl = startNode();
decl.id = parseIdent();
if (strict && isStrictBadIdWord(decl.id.name))
raise(decl.id.start, "Binding " + decl.id.name + " in strict mode");
decl.init = eat(_eq) ? parseExpression(true, noIn) : null;
node.declarations.push(finishNode(decl, "VariableDeclarator"));
if (!eat(_comma)) break;
}
return finishNode(node, "VariableDeclaration");
}
// ### Expression parsing
// These nest, from the most general expression type at the top to
// 'atomic', nondivisible expression types at the bottom. Most of
// the functions will simply let the function(s) below them parse,
// and, *if* the syntactic construct they handle is present, wrap
// the AST node that the inner parser gave them in another node.
// Parse a full expression. The arguments are used to forbid comma
// sequences (in argument lists, array literals, or object literals)
// or the `in` operator (in for loops initalization expressions).
function parseExpression(noComma, noIn) {
var expr = parseMaybeAssign(noIn);
if (!noComma && tokType === _comma) {
var node = startNodeFrom(expr);
node.expressions = [expr];
while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
return finishNode(node, "SequenceExpression");
}
return expr;
}
// Parse an assignment expression. This includes applications of
// operators like `+=`.
function parseMaybeAssign(noIn) {
var left = parseMaybeConditional(noIn);
if (tokType.isAssign) {
var node = startNodeFrom(left);
node.operator = tokVal;
node.left = left;
next();
node.right = parseMaybeAssign(noIn);
checkLVal(left);
return finishNode(node, "AssignmentExpression");
}
return left;
}
// Parse a ternary conditional (`?:`) operator.
function parseMaybeConditional(noIn) {
var expr = parseExprOps(noIn);
if (eat(_question)) {
var node = startNodeFrom(expr);
node.test = expr;
node.consequent = parseExpression(true);
expect(_colon);
node.alternate = parseExpression(true, noIn);
return finishNode(node, "ConditionalExpression");
}
return expr;
}
// Start the precedence parser.
function parseExprOps(noIn) {
return parseExprOp(parseMaybeUnary(noIn), -1, noIn);
}
// Parse binary operators with the operator precedence parsing
// algorithm. `left` is the left-hand side of the operator.
// `minPrec` provides context that allows the function to stop and
// defer further parser to one of its callers when it encounters an
// operator that has a lower precedence than the set it is parsing.
function parseExprOp(left, minPrec, noIn) {
var prec = tokType.binop;
if (prec != null && (!noIn || tokType !== _in)) {
if (prec > minPrec) {
var node = startNodeFrom(left);
node.left = left;
node.operator = tokVal;
next();
node.right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);
var node = finishNode(node, /&&|\|\|/.test(node.operator) ?
"LogicalExpression" : "BinaryExpression");
return parseExprOp(node, minPrec, noIn);
}
}
return left;
}
// Parse unary operators, both prefix and postfix.
function parseMaybeUnary(noIn) {
if (tokType.prefix) {
var node = startNode(), update = tokType.isUpdate;
node.operator = tokVal;
node.prefix = true;
next();
node.argument = parseMaybeUnary(noIn);
if (update) checkLVal(node.argument);
else if (strict && node.operator === "delete" &&
node.argument.type === "Identifier")
raise(node.start, "Deleting local variable in strict mode");
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
}
var expr = parseExprSubscripts();
while (tokType.postfix && !canInsertSemicolon()) {
var node = startNodeFrom(expr);
node.operator = tokVal;
node.prefix = false;
node.argument = expr;
checkLVal(expr);
next();
expr = finishNode(node, "UpdateExpression");
}
return expr;
}
// Parse call, dot, and `[]`-subscript expressions.
function parseExprSubscripts() {
return parseSubscripts(parseExprAtom());
}
function parseSubscripts(base, noCalls) {
if (eat(_dot)) {
var node = startNodeFrom(base);
node.object = base;
node.property = parseIdent(true);
node.computed = false;
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
} else if (eat(_hash)) {
var node = startNodeFrom(base);
node.object = base;
node.computed = parseIdentNumOrParenExpr(node);
return parseSubscripts(finishNode(node, "PluckExpression"), noCalls);
} else if (eat(_bracketL)) {
var node = startNodeFrom(base);
node.object = base;
node.property = parseExpression();
node.computed = true;
expect(_bracketR);
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
} else if (!noCalls && eat(_parenL)) {
var node = startNodeFrom(base);
node.callee = base;
node.arguments = parseExprList(_parenR);
return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
} else return base;
}
// Parse a number or an identifier (used for pluck expressions).
function parseIdentNumOrParenExpr(n) {
switch (tokType) {
case _name:
n.property = parseIdent();
return false;
case _num: case _string: case _regexp:
var node = startNode();
node.value = tokVal;
node.raw = input.slice(tokStart, tokEnd);
next();
n.property = finishNode(node, "Literal");
return true;
case _parenL:
n.property = parseParenExpression();
return true;
default:
unexpected();
}
}
// Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.
function parseExprAtom() {
switch (tokType) {
case _this:
var node = startNode();
next();
return finishNode(node, "ThisExpression");
case _name:
return parseIdent();
case _num: case _string: case _regexp:
var node = startNode();
node.value = tokVal;
node.raw = input.slice(tokStart, tokEnd);
next();
return finishNode(node, "Literal");
case _null: case _true: case _false:
var node = startNode();
node.value = tokType.atomValue;
node.raw = tokType.keyword
next();
return finishNode(node, "Literal");
case _parenL:
var tokStart1 = tokStart;
next();
var val = parseExpression();
val.start = tokStart1;
val.end = tokEnd;
expect(_parenR);
return val;
case _bracketL:
var node = startNode();
next();
node.elements = parseExprList(_bracketR, true);
return finishNode(node, "ArrayExpression");
case _braceL:
return parseObj();
case _function:
var node = startNode();
next();
return parseFunction(node, false);
case _palette:
var node = startNode();
next();
return parsePalette(node);
case _interpolator:
var node = startNode();
next();
return parseInterpolator(node);
case _new:
return parseNew();
default:
unexpected();
}
}
// New's precedence is slightly tricky. It must allow its argument
// to be a `[]` or dot subscript expression, but not a call — at
// least, not without wrapping it in parentheses. Thus, it uses the
function parseNew() {
var node = startNode();
next();
node.callee = parseSubscripts(parseExprAtom(), true);
if (eat(_parenL)) node.arguments = parseExprList(_parenR);
else node.arguments = [];
return finishNode(node, "NewExpression");
}
// Parse an object literal.
function parseObj() {
var node = startNode(), first = true, sawGetSet = false;
node.properties = [];
next();
while (!eat(_braceR)) {
if (!first) {
expect(_comma);
} else first = false;
var prop = {key: parsePropertyName()}, isGetSet = false, kind;
if (eat(_colon)) {
prop.value = parseExpression(true);
kind = prop.kind = "init";
} else if (prop.key.type === "Identifier" &&
(prop.key.name === "get" || prop.key.name === "set")) {
isGetSet = sawGetSet = true;
kind = prop.kind = prop.key.name;
prop.key = parsePropertyName();
if (tokType !== _parenL) unexpected();
prop.value = parseFunction(startNode(), false);
} else unexpected();
// getters and setters are not allowed to clash — either with
// each other or with an init property — and in strict mode,
// init properties are also not allowed to be repeated.
if (prop.key.type === "Identifier" && (strict || sawGetSet)) {
for (var i = 0; i < node.properties.length; ++i) {
var other = node.properties[i];
if (other.key.name === prop.key.name) {
var conflict = kind == other.kind ||
isGetSet && other.kind === "init" ||
kind === "init" && (other.kind === "get" || other.kind === "set");
if (conflict && !strict && kind === "init" &&
other.kind === "init") conflict = false;
if (conflict) raise(prop.key.start, "Redefinition of property");
}
}
}
node.properties.push(prop);
}
return finishNode(node, "ObjectExpression");
}
function parsePropertyName() {
if (tokType === _num || tokType === _string) return parseExprAtom();
return parseIdent(true);
}
// Parse a function declaration or literal (depending on the
// `isStatement` parameter).
function parseFunction(node, isStatement) {
if (tokType === _name) node.id = parseIdent();
else if (isStatement) unexpected();
else node.id = null;
node.params = [];
var first = true;
expect(_parenL);
while (!eat(_parenR)) {
if (!first) expect(_comma); else first = false;
node.params.push(parseIdent());
}
// Start a new scope with regard to labels and the `inFunction`
// flag (restore them to their old value afterwards).
var oldInFunc = inFunction, oldLabels = labels;
inFunction = true; labels = [];
node.body = parseBlock(true);
inFunction = oldInFunc; labels = oldLabels;
// If this is a strict mode function, verify that argument names
// are not repeated, and it does not try to bind the words `eval`
// or `arguments`.
if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
for (var i = node.id ? -1 : 0; i < node.params.length; ++i) {
var id = i < 0 ? node.id : node.params[i];
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
raise(id.start, "Defining '" + id.name + "' in strict mode");
if (i >= 0) for (var j = 0; j < i; ++j)
if (id.name === node.params[j].name)
raise(id.start, "Argument name clash in strict mode");
}
}
return finishNode(node, isStatement ?
"FunctionDeclaration" : "FunctionExpression");
}
function parsePalette(node) {
// Possible formats are:
//
// @P{colour:colour} G
// @P{colour;colour;colour...} C
// @P{type interp banded value colour; value colour...} D/A/N
//
// The "type" value is mandatory and can be one of "norm", "abs"
// or "discrete" or abbreviations of them (i.e. "n" or "N", "a" or
// "A" and "d" or "D"); "interp" and "banded" are both optional --
// valid values for "interp" are "RGB", "HSL", "HCL" or "Lab";
// "banded" is just a present/absent flag.
//
// The "value" items are numbers, and "colour" items are either
// names or of the form #XXX or #XXXXXX, where X is a hex digit.
var type, tmp;
expect(_braceL);
if (tokType == _name) {
tmp = parseIdent().name.toLowerCase();
if ("discrete".substr(0, tmp.length) == tmp) type = 'discrete';
else if ("absolute".substr(0, tmp.length) == tmp) type = 'absolute';
else if ("normalised".substr(0, tmp.length) == tmp) type = 'normalised';
else if (eat(_semi)) type = 'colours';
else if (eat(_colon)) type = 'gradient';
else raise("Invalid palette specification");
} else if (tokType == _hash) {
readToken(false, true); tmp = '#' + tokVal; next();
if (eat(_semi)) type = 'colours';
else if (eat(_colon)) type = 'gradient';
else raise("Invalid palette specification");
} else type = 'normalised';
var paldef = { type:type };
switch (type) {
case 'gradient': {
var col1 = tmp, col2;
if (tokType == _name)
col2 = parseIdent().name.toLowerCase();
else if (tokType == _hash) {
readToken(false, true); col2 = '#' + tokVal; next();
} else raise("Invalid palette specification");
expect(_braceR);
paldef = { type:"normalised", values:[0,1], colours:[col1,col2] };
break;
}
case 'colours': {
var cols = [tmp], first = false;
while (!eat(_braceR)) {
if (!first) expect(_semi); else first = false;
if (tokType == _name)
cols.push(parseIdent().name.toLowerCase());
else if (tokType == _hash) {
readToken(false, true); cols.push('#' + tokVal); next();
} else raise("Invalid palette specification");
}
paldef = { type:"discrete", values:null, colours:cols };
break;
}
case 'absolute':
case 'normalised':
// Deal with optional tags.
if (tokType == _name &&
(tokVal == 'banded' || tokVal == 'rgb' || tokVal == 'hsl' ||
tokVal == 'hcl' || tokVal == 'lab')) {
if (tokVal == 'banded') { paldef.banded = true; next(); }
else {
paldef.interp = tmp; next();
if (tokType == _name && tokVal == 'banded') {
paldef.banded = true; next();
}
}
}
// DELIBERATE FALL-THROUGH TO NEXT CASE!
case 'discrete':
// We are now lined up at the beginning of the (value, colour)
// pairs.
var first, vals, cols;
first = true; vals = []; cols = [];
while (!eat(_braceR)) {
if (!first) eat(_semi); else first = false;
if (tokType == _name) vals.push(parseIdent().name);
else if (tokType == _plusmin) {
var sign = tokVal == '-' ? (-1) : 1;
next();
if (tokType != _num) raise("Invalid palette specification");
vals.push(sign * tokVal); next();
} else if (tokType == _num) { vals.push(tokVal); next(); }
else raise("Invalid palette specification");
if (tokType == _name) cols.push(parseIdent().name.toLowerCase());
else if (tokType == _hash) {
readToken(false, true); cols.push('#' + tokVal); next();
}
else raise("Invalid palette specification");
}
paldef.values = vals;
paldef.colours = cols;
}
var node = startNode();
node.palette = paldef;
return finishNode(node, "PaletteExpression");
};
// Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with
// nothing in between them to be parsed as `null` (which is needed
// for array literals).
function parseExprList(close, allowEmpty) {
var elts = [], first = true;
while (!eat(close)) {
if (!first) {
expect(_comma);
} else first = false;
if (allowEmpty && tokType === _comma) elts.push(null);
else elts.push(parseExpression(true));
}
return elts;
}
// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.
function parseIdent(liberal) {
var node = startNode();
node.name = tokType === _name ?
tokVal : (liberal && tokType.keyword) || unexpected();
next();
return finishNode(node, "Identifier");
}
return mainfn;
});
// Helper service to allow overriding of default use of $http for
// accessing plot data defined via a SRC attribute. This can be
// useful to implement client-side caching of plot data, for example.
radian.factory('plotDataHttp', ['$http', function($http)
{
var p = { provider: $http };
function set(prov) { p.provider = prov; };
p.set = set;
return p;
}]);
// Bring plot data into Angular scope by parsing <plot-data> directive
// body.
radian.directive('plotData',
['$http', 'processAttrs', 'plotDataHttp',
function($http, processAttrs, plotDataHttp)
{
'use strict';
// Recursively transform any string values that can be parsed as
// numbers into numeric values.
function numberTypes(d) {
if (typeof d == 'object') {
var n;
Object.keys(d).forEach(function(k) {
switch (typeof d[k]) {
case 'object':
if (d[k]) numberTypes(d[k]);
break;
case 'string':
n = Number(d[k]);
if (!isNaN(n)) d[k] = n;
break;
}
});
}
};
// Parse JSON or CSV data.
function parseData(datatext, format, cols, separator) {
var d;
var fpre = /^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$/;
switch (format) {
case 'json':
try {
d = typeof datatext == 'string' ? JSON.parse(datatext) : datatext;
numberTypes(d);
}
catch (e) { throw Error('invalid JSON data in <plot-data>'); }
break;
case 'csv':
try {
d = $.csv.toArrays(datatext.replace(/^\s*\n/g, '').split('\n')
.map(function(s) {
return s.replace(/^\s+/, '');
}).join('\n'),
{ separator: separator });
if (d.length > 0) {
if (cols) {
if (d[0].length != cols.length)
throw Error('mismatch between COLS and' +
' CSV data in <plot-data>');
} else {
cols = d[0];
d.splice(0, 1);
}
var tmp = { }, nums = [];
for (var c = 0; c < cols.length; ++c) {
tmp[cols[c]] = [];
nums.push(d[0][c].match(fpre));
}
for (var i = 0; i < d.length; ++i)
for (var c = 0; c < cols.length; ++c) {
if (nums[c])
tmp[cols[c]].push(parseFloat(d[i][c]));
else
tmp[cols[c]].push(d[i][c]);
}
d = tmp;
}
} catch (e) { throw Error('invalid CSV data in <plot-data>'); }
}
return d;
};
// Date field processing.
function dateProcess(d, k, f) {
function go(x, active) {
if (x instanceof Array && x.length > 0) {
if (typeof x[0] == 'string' && active)
x.forEach(function(v, i) { x[i] = f(v); });
else
x.forEach(function(v) { go(v, false); });
} else if (typeof x == 'object') {
if (x.hasOwnProperty(k) && !(x[k] instanceof Array))
x[k] = f(x[k]);
else
Object.keys(x).forEach(function(xk) { go(x[xk], xk == k); });
}
}
go(d, false);
};
// Process all date fields.
function processDates(scope, dataset, d) {
if (scope[dataset] && scope[dataset].metadata) {
for (var k in scope[dataset].metadata) {
var md = scope[dataset].metadata[k];
if (md.format == 'date') {
if (!md.dateParseFormat)
dateProcess(d, k, function(v) { return new Date(v); });
else {
var parse;
if (md.dateParseFormat == 'isodate')
parse = d3.time.format.iso.parse;
else
parse = d3.time.format(md.dateParseFormat).parse;
dateProcess(d, k, function(v) { return parse(v); });
}
}
}
}
};
// We use a post-link function here so that any enclosed <metadata>
// directives will have been linked by the time we get here.
function postLink(sc, elm, as) {
// The <plot-data> element is only there to carry data, so hide
// it right away.
elm.hide();
// Process attributes.
processAttrs(sc, as);
if (!as.hasOwnProperty('name'))
throw Error('<plot-data> must have NAME attribute');
var dataset = sc.name;
var subname = as.hasOwnProperty('subname') ? sc.subname : undefined;
var format = as.hasOwnProperty('format') ? sc.format : 'json';
var sep = as.hasOwnProperty('separator') ?
(sc.separator === '' ? ' ' : (sc.separator || ',')) : ',';
var cols = as.hasOwnProperty('cols') ? sc.cols : undefined;
if (cols) cols = cols.split(',').map(function (s) { return s.trim(); });
if (!as.hasOwnProperty('src')) {
var formats = ['json', 'csv'];
if (formats.indexOf(format) == -1)
throw Error('invalid FORMAT "' + format + '" in <plot-data>');
}
// Get plot data via a HTTP request.
function getData() {
sc.firstDataLoad = true;
plotDataHttp.provider.get(sc.src)
.success(function(data, status, headers, config) {
if (headers("Content-Type").indexOf('application/json') == 0)
format = 'json';
processData(data);
})
.error(function() {
throw Error("failed to read data from " + sc.src);
});
};
// Process content -- all text children are appended together
// for parsing.
function processData(datatext) {
// Parse data.
var d = parseData(datatext, format, cols, sep);
// Process any date fields.
processDates(sc, dataset, d);
// Install data on nearest enclosing scope that isn't associated
// with an ng-repeat. Preserve any metadata.
var md = sc[dataset] ? sc[dataset].metadata : null;
var s = sc.$parent;
while (s.$parent && s.hasOwnProperty('$index')) s = s.$parent;
if (sc.subname) {
s[dataset][subname] = d;
if (md) s[dataset][subname].metadata = md;
} else {
s[dataset] = d;
if (md) s[dataset].metadata = md;
}
};
if (as.hasOwnProperty('src') && sc.src)
getData();
else {
var datatext = '';
if (as.hasOwnProperty('ngModel')) {
datatext = sc.$eval(as.ngModel);
sc.$watch(as.ngModel, function(n, o) {
if (n == undefined || n == o) return;
datatext = sc.$eval(as.ngModel);
processData(datatext);
}, true);
}
if (datatext == '') {
elm.contents().each(function(i,n) {
if (n instanceof Text) datatext += n.textContent;
});
}
processData(datatext);
}
sc.$watch('src', function(n, o) {
if (n == undefined || n == o && sc.firstDataLoad) return;
getData();
});
};
return {
restrict: 'E',
scope: true,
compile: function(elm, as, trans) {
return { post: postLink };
}
};
}]);
radian.directive('metadata', [function()
{
'use strict';
return {
restrict: 'E',
scope: false,
link: function(scope, elm, as) {
// Identify the data set that we're metadata for.
if (!elm[0].parentNode || elm[0].parentNode.tagName != 'PLOT-DATA' ||
!$(elm[0].parentNode).attr('name'))
throw Error('<metadata> not properly nested inside <plot-data>');
var dataset = $(elm[0].parentNode).attr('name');
// Copy metadata attributes into a new object.
if (!as.name) throw Error('<metadata> without NAME attribute');
var name = as.name;
var md = { };
[ 'dateFormat', 'dateParseFormat', 'errorFor',
'format', 'label', 'units', 'categoryOrder' ].forEach(function(a) {
if (as.hasOwnProperty(a)) md[a] = as[a];
});
// Set up metadata for this data set.
if (!scope[dataset]) scope[dataset] = { metadata: { } };
if (!scope[dataset].metadata)
scope[dataset].metadata = { };
scope[dataset].metadata[name] = md;
}
};
}]);
// Deal with plot layout and processing for <plot-row>, <plot-col>,
// <plot-grid> and <plot-layout> directives.
// How much relative space a plot takes up in the current layout
// direction is specified as a number or nothing (if the plot will be
// sized according to the average size of plots in the box).
//
// A layout is made up of plots arranged in horizontal boxes and
// vertical boxes. A single <plot> directive manages its own layout
// (which is trivial).
//
// Within the data structures for managing layouts, individual plots
// are represented by their associated Angular scopes.
//
// If we have some plots, A, B, C, D, which we'll represent by
// $scopeA, $scopeB, etc., then here's how we represent some example
// layouts:
//
// +---+ +---+
// | A | | B | ["hbox", [$scopeA, $scopeB]]
// +---+ +---+
//
// +---+
// | A | ["vbox", [$scopeA, $scopeB]]
// +---+
// +---+
// | B |
// +---+
//
// +---+ +---+
// | A | | B | ["vbox", ["hbox", [$scopeA, $scopeB]],
// +---+ +---+ ["hbox", [$scopeC, $scopeD]]]
// +---+ +---+
// | C | | D |
// +---+ +---+
//
// +---+ +---+
// | A | | | ["hbox", ["vbox", [$scopeA, $scopeB, $scopeC]],
// +---+ | | $scopeD]
// +---+ | |
// | B | | D |
// +---+ | |
// +---+ | |
// | C | | |
// +---+ +---+
//
// +-------+ +----+
// | | | | ["hbox", [[3, $scopeA], [2, $scopeB]]]
// | A | | B |
// | | | |
// +-------+ +----+
//
// +--------------+ (Here, B is supposed to be a box two rows high.)
// | A |
// | | ["vbox", [[2, $scopeA], [1, $scopeB], [3, $scopeC]]]
// +--------------+
// +------B-------+
// +--------------+
// +--------------+
// | |
// | |
// | C |
// | |
// | |
// +--------------+
//
// In Haskell, a layout is defined as
//
// data Layout a = HBox [(a, Layout a)]
// | VBox [(a, Layout a)]
// | Frame String
// deriving (Eq, Show)
//
// where a is a type parameterising the size specifications for the
// individual plots. As specified by the user, a ~ Maybe (Ratio Int),
// and using Nothing means that a plot should just take up the
// "average" space. For rendering, the Layout (Maybe (Ratio Int))
// type is transformed into a Layout Int which specifies the actual
// dimensions of the plots. This transformation is the job of the
// layoutSizes function.
radian.factory('layoutSizes', ['layoutToString', function(layoutToString) {
'use strict';
// Determine sizes of frames in a layout.
return function(w, h, spc, layout)
{
// Fit a range of space parameters into a given size and spacing.
function fitSizes(w, ws)
{
var realw = w - spc * (ws.length - 1);
var vs = ws.filter(function(x) { return x != null; });
function sum(a) { return a.reduce(function(a,b) { return a+b; }, 0); };
var mean = vs.length == 0 ? 1 : sum(vs) / vs.length;
var realvals = ws.map(function(x) { return x == null ? mean : x; });
var realtot = sum(realvals);
var widths = realvals.map(function(x) {
return Math.floor(x * realw / realtot);
});
var wdiff = realw - sum(widths);
if (wdiff != 0) {
var outspc = Math.floor(ws.length / wdiff);
for (var i = 0; i < ws.length; ++i)
if (i % (outspc + 1) == 0) ++widths[i];
}
return widths;
};
function help(w, h, layout)
{
if (layout.type == 'plot' || layout.type == 'empty') return layout;
function getratios(ls) {
return ls.map(function(l) { return l.size || null; });
};
var sizes =
fitSizes(layout.type == 'hbox' ? w : h, getratios(layout.items));
var outitems = [];
for (var i = 0; i < layout.items.length; ++i) {
if (layout.type == 'hbox')
outitems[i] = { size: sizes[i],
item: help(sizes[i], h, layout.items[i].item) };
else
outitems[i] = { size: sizes[i],
item: help(w, sizes[i], layout.items[i].item) };
}
return { type: layout.type, items: outitems };
};
var sub = help(w, h, layout);
if (layout.type == 'hbox')
return { type: 'vbox', items: [{ size: h, item: sub }] };
else if (layout.type == 'vbox')
return { type: 'hbox', items: [{ size: w, item: sub }] };
else
return { type:'hbox',
items: [{ size: w, item: { type: 'vbox', items: sub }}]};
};
}]);
radian.factory('addToLayout', function()
{
return function(sc, sublayout, size, elm) {
if (sublayout.hasOwnProperty('$id'))
sc.layoutItems.push({ size: size != null ? Number(size) : null,
item: { type: 'plot', items: sublayout }});
else
sc.layoutItems.push({ size: size != null ? Number(size) : null,
item: sublayout });
};
});
radian.factory('extractFrames',
['layoutToString',
function(layoutToString)
{
// A "frame" is an object of the form { x, y, w, h, plot }, where
// plot points to the plot scope.
return function(spc, w, h, layout) {
function go(curx, cury, curw, curh, lay) {
var frames = [];
if (lay.type == 'hbox') {
for (var i = 0; i < lay.items.length; ++i) {
var item = lay.items[i].item;
var itype = lay.items[i].item.type;
var isize = lay.items[i].size;
if (item.type == 'plot') {
frames.push({ x: curx, y: cury, w: isize, h: curh,
plot: item.items });
} else if (item.type == 'vbox') {
frames = frames.concat(go(curx, cury, isize, curh, item));
}
curx += isize + spc;
}
} else if (lay.type == 'vbox') {
for (var i = 0; i < lay.items.length; ++i) {
var item = lay.items[i].item;
var itype = lay.items[i].item.type;
var isize = lay.items[i].size;
if (item.type == 'plot') {
frames.push({ x: curx, y: cury, w: curw, h: isize,
plot: item.items });
} else if (item.type == 'hbox') {
frames = frames.concat(go(curx, cury, curw, isize, item));
}
cury += isize + spc;
}
} else throw Error("invalid layout passed to extractFrames");
return frames;
};
return go(0, 0, w, h, layout);
};
}]);
radian.factory('layoutDirective',
['layoutSizes', 'processAttrs', 'calcPlotDimensions',
'addToLayout', 'extractFrames', 'layoutToString',
function(layoutSizes, processAttrs, calcPlotDimensions,
addToLayout, extractFrames, layoutToString)
{
'use strict';
return function(container) {
function preLink(sc, elm, as, transclude) {
processAttrs(sc, as);
if (!sc.inLayout) {
sc.layoutTop = true;
sc.inLayout = true;
if (!sc.inStack) calcPlotDimensions(sc, elm, as);
$(elm).css('width', sc.pxwidth).css('height', sc.pxheight);
sc.layoutsvg = elm.children()[0];
}
sc.layoutItems = [];
transclude(sc.$new(), function (cl) { elm.append(cl); });
};
function postLink(sc, elm) {
if (sc.inLayout && !sc.hasOwnProperty('layoutTop'))
$(elm.children()[0]).remove();
var items = { type: container, items: sc.layoutItems };
if (sc.hasOwnProperty('layoutTop')) {
var spacing = sc.spacing || 0;
var layedout = layoutSizes(sc.pxwidth, sc.pxheight, spacing, items);
var frames = extractFrames(0, sc.pxwidth, sc.pxheight, layedout);
if (sc.hasOwnProperty('title')) items.title = sc.title;
frames.forEach(function(fr) {
fr.plot.pxwidth = fr.w;
fr.plot.pxheight = fr.h;
$(fr.plot.topelem).css('width', fr.w).css('height', fr.h).
css('top', fr.y).css('left', fr.x);
fr.plot.svg = d3.select(sc.layoutsvg).append('g')
.attr('width', fr.w).attr('height', fr.h)
.attr('transform', 'translate(' + fr.x + ',' + fr.y + ')')[0][0];
});
}
if (!sc.hasOwnProperty('layoutTop') || sc.inStack)
addToLayout(sc.$parent, items, sc.layoutShare, elm);
};
return {
restrict: 'E',
template: '<div class="radian" style="top: 0px; left: 0px">' +
'<svg></svg>' +
'</div>',
replace: true,
transclude: true,
scope: true,
compile: function(elm, as, trans) {
return { pre: function(s, e, a) { preLink(s, e, a, trans); },
post: postLink };
}
};
};
}]);
radian.directive('plotRow', ['layoutDirective', function(layoutDirective)
{
return layoutDirective('hbox');
}]);
radian.directive('plotCol', ['layoutDirective', function(layoutDirective)
{
return layoutDirective('vbox');
}]);
radian.directive('plotGrid',
['layoutSizes', 'processAttrs', 'calcPlotDimensions',
'addToLayout', 'extractFrames', 'layoutToString',
function(layoutSizes, processAttrs, calcPlotDimensions,
addToLayout, extractFrames, layoutToString)
{
'use strict';
function preLink(sc, elm, as, transclude) {
processAttrs(sc, as);
if (!sc.inLayout) {
sc.layoutTop = true;
sc.inLayout = true;
if (!sc.inStack) calcPlotDimensions(sc, elm, as);
$(elm).css('width', sc.pxwidth).css('height', sc.pxheight);
sc.layoutsvg = elm.children()[0];
}
sc.layoutItems = [];
transclude(sc.$new(), function (cl) { elm.append(cl); });
};
function postLink(sc, elm) {
if (sc.inLayout && !sc.hasOwnProperty('layoutTop'))
$(elm.children()[0]).remove();
var nrows = sc.rows || Math.floor(Math.sqrt(sc.layoutItems.length));
var ncols = sc.cols || Math.ceil(sc.layoutItems.length / nrows);
var rows = [];
var i = 0;
for (var r = 0; r < nrows; ++r) {
var cols = [];
for (var c = 0; c < ncols; ++c) {
if (i >= sc.layoutItems.length)
cols.push({ size: null, item: { type: 'empty' } });
else
cols.push(sc.layoutItems[i++]);
}
rows.push({ size: null, item: { type: 'hbox', items: cols } });
}
var items = { type: 'vbox', items: rows };
if (sc.hasOwnProperty('layoutTop')) {
var spacing = sc.spacing || 0;
var layedout = layoutSizes(sc.pxwidth, sc.pxheight, spacing, items);
var frames = extractFrames(0, sc.pxwidth, sc.pxheight, layedout);
if (sc.hasOwnProperty('title')) items.title = sc.title;
frames.forEach(function(fr) {
fr.plot.pxwidth = fr.w;
fr.plot.pxheight = fr.h;
$(fr.plot.topelem).css('width', fr.w).css('height', fr.h).
css('top', fr.y).css('left', fr.x);
fr.plot.svg = d3.select(sc.layoutsvg).append('g')
.attr('width', fr.w).attr('height', fr.h)
.attr('transform', 'translate(' + fr.x + ',' + fr.y + ')')[0][0];
});
}
if (!sc.hasOwnProperty('layoutTop') || sc.inStack)
addToLayout(sc.$parent, items, sc.layoutShare, elm);
};
return {
restrict: 'E',
template: '<div class="radian" style="top: 0px; left: 0px">' +
'<svg></svg>' +
'</div>',
replace: true,
transclude: true,
scope: true,
compile: function(elm, as, trans) {
return { pre: function(s, e, a) { preLink(s, e, a, trans); },
post: postLink };
}
};
}]);
radian.directive('plotStack',
['$rootScope', 'layoutSizes', 'processAttrs', 'calcPlotDimensions',
'addToLayout', 'extractFrames', 'layoutToString',
function($rootScope, layoutSizes, processAttrs, calcPlotDimensions,
addToLayout, extractFrames, layoutToString)
{
'use strict';
function preLink(sc, elm, as, transclude) {
processAttrs(sc, as);
if (sc.inLayout)
throw Error("<plot-stack> cannot appear inside other layout directives");
if (!sc.inStack) calcPlotDimensions(sc, elm, as);
if (sc.inStack) addToLayout(sc.$parent, { type: 'stack', items: sc },
null, elm);
sc.inStack = true;
sc.layoutItems = [];
if (!$rootScope.radianNavIDs) $rootScope.radianNavIDs = { };
transclude(sc.$new(), function (cl) {
elm.append('<div class="tab-content radian-tabs"></div>');
var tabs = elm.children(0);
tabs.append(cl);
sc.ids = [];
cl.filter('div.radian,div.radian-stack').each(function(i) {
var idx = 0, tabid;
do {
++idx;
tabid = 'tab' + idx + '_' + i;
} while ($rootScope.radianNavIDs[tabid]);
sc.ids.push(tabid);
$rootScope.radianNavIDs[tabid] = 1;
var cls = i == 0 ? 'tab-pane active' : 'tab-pane';
$(this).wrap('<div class="' + cls + '" id="' + tabid + '"></div>');
});
});
};
function postLink(sc, elm) {
var is = sc.layoutItems;
elm.prepend('<ul class="nav nav-tabs"></ul>');
var nav = elm.children('ul');
for (var i = 0; i < is.length; ++i) {
var it = is[i].item;
var t = it.title ? it.title :
(it.items.title ? it.items.title : 'Tab ' + (i+1));
var link = '<a href="#' + sc.ids[i] + '" data-toggle="tab">' + t + '</a>';
var active = i == 0 ? ' class="active"' : '';
nav.append('<li' + active + '>' + link + '</li>');
}
};
return {
restrict: 'E',
template: '<div class="radian-stack"></div>',
replace: true,
transclude: true,
scope: true,
compile: function(elm, as, trans) {
return { pre: function(s, e, a) { preLink(s, e, a, trans); },
post: postLink };
}
};
}]);
radian.factory('layoutToString', function() {
'use strict';
return function(layout) {
function fixplots(lay) {
switch (lay.type) {
case 'empty': return { type: 'empty' };
case 'plot': return { type: 'plot', items: lay.items.$id };
default: return { type: lay.type, items: lay.items.map(function(i) {
return { size: i.size, item: fixplots(i.item) };
}) };
}
};
return JSON.stringify(fixplots(layout));
};
});
// Line plots.
radian.factory('drawLinesGeneric', function()
{
'use strict';
return function(svg, x, xs, y, ys, s, setupPlotXY) {
function sty(v) {
return (v instanceof Array) ? function(d, i) { return v[i]; } : v;
};
function sty0(v) {
return (v instanceof Array) ? function(d, i) { return v[0]; } : v;
};
function apSc(sc, d, i) {
var dtmp = d;
if (sc.oton) dtmp = sc.oton(d);
return sc(dtmp, i);
};
var width = s.strokeWidth || 1;
var opacity = s.strokeOpacity || 1.0;
var stroke = s.stroke || '#000';
var ssel = s.$eval('strokesel');
if (stroke instanceof Array && s.$eval('strokesel') !== undefined)
stroke = ssel ? stroke[ssel % stroke.length] : stroke[0];
var missing = s.missing || 'interpolate';
var gapMarker = s.gapMarker || 'circle';
var gapMarkerSize = s.gapMarkerSize || Math.pow(width * 2, 2);
var gapMarkerStroke = s.gapMarkerStroke || stroke;
var gapMarkerStrokeWidth = s.gapMarkerStrokeWidth || width;
var gapMarkerFill = s.gapMarkerFill || stroke;
var gapMarkerStrokeOpacity = s.gapMarkerStrokeOpacity || opacity;
var gapMarkerFillOpacity = s.gapMarkerFillOpacity || opacity;
// Deal with along-stroke interpolation.
if (stroke instanceof Function) {
var tmp = new Array(x.length);
for (var i = 0; i < x.length; ++i) tmp[i] = i / x.length;
stroke = stroke(tmp);
}
// Plot-type dependent data setup.
var tmpx = [], tmpy = [];
setupPlotXY(x, tmpx, y, tmpy);
// Deal with missing values.
var plotx = [], ploty = [], plotstr = [], plotwid = [], plotopa = [];
switch (missing) {
case 'interpolate': {
// If we're interpolating over missing values, just elide any
// missing data points and build a single segment.
var curx = [], cury = [], curstr = [], curwid = [], curopa = [];
for (var i = 0; i < tmpx.length; ++i) {
if (tmpy[i] !== null && !isNaN(tmpy[i])) {
curx.push(tmpx[i]);
cury.push(tmpy[i]);
if (width instanceof Array) curwid.push(width[i]);
if (opacity instanceof Array) curopa.push(opacity[i]);
if (stroke instanceof Array) curstr.push(stroke[i]);
}
}
plotx.push(curx); ploty.push(cury);
plotstr.push(curstr); plotwid.push(curwid); plotopa.push(curopa);
break;
}
case 'gap': {
// If we're gapping missing values, elide missing data points
// and build segments for each run of contiguous non-missing
// points.
var curx = [], cury = [], curstr = [], curwid = [], curopa = [];
for (var i = 0; i < tmpx.length; ++i) {
if (tmpy[i] === null || isNaN(tmpy[i])) {
// End of segment.
if (curx.length > 0) {
plotx.push(curx); ploty.push(cury);
plotstr.push(curstr); plotwid.push(curwid); plotopa.push(curopa);
curx = []; cury = []; curstr = []; curwid = []; curopa = [];
}
} else {
curx.push(tmpx[i]);
cury.push(tmpy[i]);
if (width instanceof Array) curwid.push(width[i]);
if (opacity instanceof Array) curopa.push(opacity[i]);
if (stroke instanceof Array) curstr.push(stroke[i]);
}
}
// Last segment.
if (curx.length > 0) {
plotx.push(curx); ploty.push(cury);
plotstr.push(curstr); plotwid.push(curwid); plotopa.push(curopa);
}
break;
}
}
// Switch on type of stroke...
if (!(width instanceof Array || opacity instanceof Array ||
stroke instanceof Array)) {
// Normal lines; one path per segment, potentially with gaps.
var line = d3.svg.line()
.x(function (d, i) { return xs.ap(d[0], i); })
.y(function (d, i) { return apSc(ys, d[1], i); });
var points =
d3.svg.symbol().type(sty0(gapMarker)).size(sty0(gapMarkerSize));
for (var seg = 0; seg < plotx.length; ++seg) {
var segx = plotx[seg], segy = ploty[seg];
var segwid = plotwid[seg], segopa = plotopa[seg], segstr = plotstr[seg];
if (segx.length > 1) {
svg.append('path').datum(d3.zip(segx, segy))
.attr('class', 'line').attr('d', line)
.style('fill', 'none')
.style('stroke-width', width instanceof Array ? segwid : width)
.style('stroke-opacity',
opacity instanceof Array ? segopa : opacity)
.style('stroke', stroke instanceof Array ? segstr : stroke);
} else {
svg.append('g').selectAll('path').data(d3.zip(segx, segy))
.enter().append('path')
.attr('transform', function(d, i) {
return 'translate(' + xs.ap(d[0], i) + ',' +
apSc(ys, d[1], i) + ')';
})
.attr('d', points)
.style('fill', sty0(gapMarkerFill))
.style('fill-opacity', sty0(gapMarkerFillOpacity))
.style('stroke-width', sty0(gapMarkerStrokeWidth))
.style('stroke-opacity', sty0(gapMarkerStrokeOpacity))
.style('stroke', sty0(gapMarkerStroke));
}
}
} else {
// Multiple paths to deal with varying characteristics along
// line.
var points =
d3.svg.symbol().type(sty0(gapMarker)).size(sty0(gapMarkerSize));
for (var seg = 0; seg < plotx.length; ++seg) {
var segx = plotx[seg], segy = ploty[seg];
var segwid = plotwid[seg], segopa = plotopa[seg], segstr = plotstr[seg];
if (segx.length > 1) {
var maxsegments = 200;
var ptsperseg = Math.max(1, Math.floor(x.length / maxsegments));
var based = d3.zip(segx, segy), lined = [];
var widths = [], opacities = [], strokes = [];
var i0 = 0, i1 = ptsperseg;
while (i0 < segx.length) {
lined.push(based.slice(i0, i1+1));
var imid = Math.floor((i0 + i1) / 2);
widths.push(width instanceof Array ? segwid[imid] : width);
opacities.push(opacity instanceof Array ? segopa[imid] : opacity);
strokes.push(stroke instanceof Array ? segstr[imid] : stroke);
i0 = i1;
i1 = i0 + ptsperseg;
}
svg.selectAll('path').data(lined).enter().append('path')
.attr('class', 'line')
.style('stroke-width', function(d, i) { return widths[i]; })
.style('stroke-opacity', function(d, i) { return opacities[i]; })
.style('stroke', function(d, i) { return strokes[i]; })
.style('fill', 'none')
.attr('d', d3.svg.line()
.x(function (d, i) { return xs.ap(d[0], i); })
.y(function (d, i) { return apSc(ys, d[1], i); }));
} else {
svg.append('g').selectAll('path').data(d3.zip(segx, segy))
.enter().append('path')
.attr('transform', function(d, i) {
return 'translate(' + xs.ap(d[0], i) + ',' +
apSc(ys, d[1], i) + ')';
})
.attr('d', points)
.style('fill', sty0(gapMarkerFill))
.style('fill-opacity', sty0(gapMarkerFillOpacity))
.style('stroke-width', sty0(gapMarkerStrokeWidth))
.style('stroke-opacity', sty0(gapMarkerStrokeOpacity))
.style('stroke', sty0(gapMarkerStroke));
}
}
}
};
});
radian.directive('vlines',
['plotTypeLink', 'drawLinesGeneric',
function(plotTypeLink, drawLinesGeneric)
{
'use strict';
function draw(svg, x, xs, y, ys, s) {
function setupPlotXY(x, plotx, y, ploty) {
x.forEach(function(v) {
plotx.push(v); ploty.push(-1000);
plotx.push(v); ploty.push(1000);
});
};
drawLinesGeneric(svg, x, xs, y, ys, s, setupPlotXY);
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.$on('setupExtra', function() {
var width = scope.strokeWidth instanceof Array &&
scope.strokeWidth.length > 0 ?
scope.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(scope.strokeWidth) || 1);
scope.rangeExtendPixels([width/2, width/2], [width/2, width/2]);
});
scope.checkPlottable = function(xvar, yvar) { return xvar; };
plotTypeLink('vlines', scope, elm, as, draw);
}
};
}]);
radian.directive('hlines',
['plotTypeLink', 'drawLinesGeneric',
function(plotTypeLink, drawLinesGeneric)
{
'use strict';
function draw(svg, x, xs, y, ys, s) {
function setupPlotXY(x, plotx, y, ploty) {
y.forEach(function(v) {
ploty.push(v); plotx.push(-1000);
ploty.push(v); plotx.push(1000);
});
};
drawLinesGeneric(svg, x, xs, y, ys, s, setupPlotXY);
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.$on('setupExtra', function() {
var width = scope.strokeWidth instanceof Array &&
scope.strokeWidth.length > 0 ?
scope.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(scope.strokeWidth) || 1);
scope.rangeExtendPixels([width/2, width/2], [width/2, width/2]);
});
scope.checkPlottable = function(xvar, yvar) { return yvar; };
plotTypeLink('hlines', scope, elm, as, draw);
}
};
}]);
radian.directive('lines',
['plotTypeLink', 'drawLinesGeneric',
function(plotTypeLink, drawLinesGeneric)
{
'use strict';
function draw(svg, x, xs, y, ys, s) {
function setupPlotXY(x, plotx, y, ploty) {
x.forEach(function(v) { plotx.push(v); });
y.forEach(function(v) { ploty.push(v); });
};
drawLinesGeneric(svg, x, xs, y, ys, s, setupPlotXY);
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.$on('setupExtra', function() {
var width = scope.strokeWidth instanceof Array &&
scope.strokeWidth.length > 0 ?
scope.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(scope.strokeWidth) || 1);
scope.rangeExtendPixels([width/2, width/2], [width/2, width/2]);
});
plotTypeLink('lines', scope, elm, as, draw);
}
};
}]);
// Scatter/bubble plots.
radian.directive('points',
['plotTypeLink', function(plotTypeLink)
{
'use strict';
function draw(svg, x, xs, y, ys, s) {
var marker = s.marker || "circle";
var strokeWidth = s.strokeWidth || 1.0;
var strokeOpacity = s.strokeOpacity || 1.0;
var fillOpacity = s.fillOpacity || 1.0;
var markerSize = s.markerSize || 1;
var orientation = s.orientation || 0.0;
var stroke, fill;
if (marker != 'text') {
stroke = s.stroke || '#000';
fill = s.fill || 'none';
} else {
stroke = s.stroke || 'none';
fill = s.fill || '#000';
}
// Plot points: plot attributes are either single values or arrays
// of values, one per point.
function sty(v) {
return (v instanceof Array) ? function(d, i) { return v[i]; } : v;
};
function fssty(v) {
return ((v instanceof Array) ? function(d, i) { return v[i]; } : v) +
'px';
};
function apSc(sc, d, i) {
var dtmp = d;
if (sc.oton) dtmp = sc.oton(d);
return sc(dtmp, i);
};
var plotx = [], ploty = [];
var plotmark = marker instanceof Array ? [] : marker;
var plotsize = markerSize instanceof Array ? [] : markerSize;
var plotstr = stroke instanceof Array ? [] : stroke;
var plotfill = fill instanceof Array ? [] : fill;
var plotwid = strokeWidth instanceof Array ? [] : strokeWidth;
var plotsopa = strokeOpacity instanceof Array ? [] : strokeOpacity;
var plotfopa = fillOpacity instanceof Array ? [] : fillOpacity;
for (var i = 0; i < x.length; ++i) {
if (y[i] !== null && !isNaN(y[i])) {
plotx.push(x[i]);
ploty.push(y[i]);
if (marker instanceof Array) plotmark.push(marker[i]);
if (markerSize instanceof Array) plotsize.push(markerSize[i]);
if (fill instanceof Array) plotfill.push(fill[i]);
if (fillOpacity instanceof Array) plotfopa.push(fillOpacity[i]);
if (stroke instanceof Array) plotstr.push(stroke[i]);
if (strokeWidth instanceof Array) plotwid.push(strokeWidth[i]);
if (strokeOpacity instanceof Array) plotsopa.push(strokeOpacity[i]);
}
}
if (marker != 'text') {
var points = d3.svg.symbol().type(sty(plotmark)).size(sty(plotsize));
svg.selectAll('path').data(d3.zip(plotx, ploty))
.enter().append('path')
.attr('transform', function(d, i) {
return 'translate(' + xs.ap(d[0], i) + ',' +
apSc(ys, d[1], i) + ')';
})
.attr('d', points)
.style('fill', sty(plotfill))
.style('fill-opacity', sty(plotfopa))
.style('stroke-width', sty(plotwid))
.style('stroke-opacity', sty(plotsopa))
.style('stroke', sty(plotstr));
} else {
var fontSize = s.markerFontSize || 12;
var fontFamily = s.markerFontFamily || (s.fontFamily || null);
var fontStyle = s.markerFontStyle || (s.fontStyle || null);
var fontWeight = s.markerFontWeight || (s.fontWeight || null);
var fontVariant = s.markerFontVariant || (s.fontVariant || null);
var markerText = s.markerText;
if (marker == 'text' && !markerText) {
markerText = new Array(x.length);
for (var i = 0; i < x.length; ++i) markerText[i] = 'X';
}
var markerAlignment = s.markerAlignment || 'centre,centre';
var as = markerAlignment.split(/,/);
var textAnchor = as[0];
var baselineShift = as.length > 1 ? as[1] : '0';
switch (textAnchor) {
case 'centre': textAnchor = 'middle'; break;
case 'left': textAnchor = 'start'; break;
case 'right': textAnchor = 'end'; break;
default: textAnchor = 'middle'; break;
}
switch (baselineShift) {
case 'centre': baselineShift = '0'; break;
case 'top': baselineShift = '-50%'; break;
case 'bottom': baselineShift = '50%'; break;
default: baselineShift = '0'; break;
}
var points = d3.svg.symbol().type(sty(plotmark)).size(sty(plotsize));
svg.selectAll('text').data(d3.zip(plotx, ploty))
.enter().append('text')
.attr('transform', function(d, i) {
return 'translate(' + xs.ap(d[0], i) + ',' +
apSc(ys, d[1], i) + ')';
})
.text(function(d, i) { return markerText[i]; })
.attr('text-anchor', textAnchor)
.style('baseline-shift', baselineShift)
.style('dominant-baseline', 'middle')
.style('font-size', fssty(fontSize))
.style('font-family', sty(fontFamily))
.style('font-style', sty(fontStyle))
.style('font-weight', sty(fontWeight))
.style('font-variant', sty(fontVariant))
.style('fill', sty(plotfill))
.style('fill-opacity', sty(plotfopa))
.style('stroke-width', sty(plotwid))
.style('stroke-opacity', sty(plotsopa))
.style('stroke', sty(plotstr));
}
};
return {
restrict: 'E',
scope: true,
link: function(s, elm, as) {
s.$on('setupExtra', function() {
if (s.marker != 'text') {
var width = s.strokeWidth instanceof Array &&
s.strokeWidth.length > 0 ?
s.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(s.strokeWidth) || 1);
if (s.stroke == 'none') width = 0;
var size = s.markerSize instanceof Array &&
s.markerSize.length > 0 ?
s.markerSize.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(s.markerSize) || 1);
var delta = (width + Math.sqrt(size)) / 2;
s.rangeExtendPixels([delta, delta], [delta, delta]);
} else {
var markerText = s.markerText;
if (!markerText) {
markerText = new Array(x.length);
for (var i = 0; i < x.length; ++i) markerText[i] = 'X';
}
var fattrs = {
size: s.markerFontSize || 12,
family: s.markerFontFamily || (s.fontFamily || null),
style: s.markerFontStyle || (s.fontStyle || null),
weight: s.markerFontWeight || (s.fontWeight || null),
variant: s.markerFontVariant || (s.fontVariant || null)
};
var maxw = 0, maxh = 0;
markerText.forEach(function(t) {
var sz = s.getTextSize(t, fattrs);
maxw = Math.max(maxw, sz.width);
maxh = Math.max(maxh, sz.height);
});
s.rangeExtendPixels([maxw, maxw], [maxh, maxh]);
}
});
plotTypeLink('points', s, elm, as, draw);
}
};
}]);
// Bar charts.
radian.directive('bars',
['plotTypeLink', 'plotLib', function(plotTypeLink, lib)
{
'use strict';
function draw(svg, xin, xs, yin, ys, s, w, h) {
var x = xin, y = yin;
var style = s.style || 'simple';
var aggregation = s.aggregation || 'none';
var strokeWidth = s.strokeWidth || 1;
var strokeOpacity = s.strokeOpacity || 1.0;
var stroke = s.stroke || '#000';
var fillOpacity = s.fillOpacity || 1.0;
var fill = s.fill || 'none';
var barMin = s.barMin || null;
var barMax = s.barMax || null;
var barWidth = s.barWidth || 1.0;
var pxBarWidth, pxWidth = false, pxSpacing = false;
if (typeof barWidth == 'string' &&
barWidth.trim().substr(-2,2) == 'px') {
pxBarWidth =
Number(barWidth.trim().substr(0, barWidth.trim().length - 2));
if (pxBarWidth < 0) pxSpacing = true;
barWidth = xs.invert(Math.abs(pxBarWidth)) - xs.invert(0);
pxBarWidth = Math.abs(pxBarWidth);
pxWidth = true;
}
var barOffset = s.barOffset || 0.0;
var pxOffset = false;
if (typeof barOffset == 'string' &&
barOffset.trim().substr(-2,2) == 'px') {
var pxoffset =
Number(barOFfset.trim().substr(0, barOffset.trim().length - 2));
barOffset = xs.invert(pxoffset) - xs.invert(0);
pxOffset = true;
}
// Data aggregation.
if (aggregation != 'none' || style != 'simple') {
var aggfn;
switch (aggregation) {
case 'mean': aggfn = lib.meanBy; break;
case 'sum': aggfn = lib.sumBy; break;
case 'max': aggfn = lib.maxBy; break;
case 'min': aggfn = lib.minBy; break;
default: throw Error("Unknown aggregation type: " + aggregation);
}
x = lib.unique(xin);
y = aggfn(yin, xin);
s.barWidths = lib.firstBy(s.barWidths, xin);
if (fill instanceof Array)
fill = lib.firstBy(fill, xin);
if (fillOpacity instanceof Array)
fillOpacity = lib.firstBy(fillOpacity, xin);
if (strokeWidth instanceof Array)
strokeWidth = lib.firstBy(strokeWidth, xin);
if (strokeOpacity instanceof Array)
strokeOpacity = lib.firstBy(strokeOpacity, xin);
if (stroke instanceof Array)
stroke = lib.firstBy(stroke, xin);
}
// Plot bars: plot attributes are either single values or arrays
// of values, one per bar.
function apSc(sc, d, i) {
var dtmp = d;
if (sc.oton) dtmp = sc.oton(d);
return sc(dtmp, i);
};
function sty(v) {
return (v instanceof Array) ? function(d, i) { return v[i]; } : v;
};
function bw(i) {
if (pxWidth) {
if (pxSpacing)
return xs.invert(xs(s.barWidths[0]) - pxBarWidth);
else
return barWidth;
} else
return s.barWidths[i] * barWidth;
};
var dat;
if (barMin && barMax)
dat = d3.zip(barMin, barMax, y);
else
dat = d3.zip(x, y);
svg.selectAll('rect').data(dat)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d, i) {
if (d.length == 3)
return xs(d[0], i);
else if (pxWidth && pxSpacing && s.axisXTransform == 'log') {
var xc = s.x[i];
var xb = i > 0 ? s.x[i-1] : xc / (s.x[i+1] / xc);
var xd = i < s.x.length - 1 ? s.x[i+1] : xc * (xc / s.x[i-1]);
var xhi = xc * Math.sqrt(xd / xc), xlo = xc * Math.sqrt(xb / xc);
var phi = xs(xhi), plo = xs(xlo);
return plo + pxBarWidth;
} else {
return d[0] instanceof Date ?
xs(new Date(d[0].valueOf() - bw(i) / 2.0 +
(pxOffset ? barOffset :
s.barWidths[i] * barOffset)), i) :
xs(xs.oton(d[0]) - bw(i) / 2.0 +
(pxOffset ? barOffset : s.barWidths[i] * barOffset), i);
}
})
.attr('y', function(d, i) { return ys(d[d.length-1], i); })
.attr('width', function(d, i) {
var ret;
if (pxWidth) {
if (pxSpacing) {
if (s.axisXTransform == 'log') {
var xc = s.x[i];
var xb = i > 0 ? s.x[i-1] : xc / (s.x[i+1] / xc);
var xd = i < s.x.length - 1 ? s.x[i+1] : xc * (xc / s.x[i-1]);
var xhi = xc * Math.sqrt(xd / xc), xlo = xc * Math.sqrt(xb / xc);
var phi = xs(xhi), plo = xs(xlo);
ret = phi - plo - pxBarWidth;
} else
ret = xs(s.barWidths[i]) - xs(0) - pxBarWidth;
} else
ret = pxBarWidth;
} else if (d.length == 3)
ret = xs(d[1], i) - xs(d[0], i);
else
ret = d[0] instanceof Date ?
xs(new Date(d[0].valueOf() + s.barWidths[i] * barWidth / 2.0), i) -
xs(new Date(d[0].valueOf() - s.barWidths[i] * barWidth / 2.0), i) :
xs(xs.oton(d[0]) + s.barWidths[i] * barWidth / 2.0, i) -
xs(xs.oton(d[0]) - s.barWidths[i] * barWidth / 2.0, i);
return ret;
})
.attr('height', function(d, i) { return h - ys(d[d.length-1]); })
.style('fill', sty(fill))
.style('fill-opacity', sty(fillOpacity))
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke));
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.$on('setupExtra', function() {
var barx = scope.x || [];
// Discrete data.
if (scope.x && scope.x instanceof Array &&
(typeof scope.x[0] == 'string' ||
scope.x[0] instanceof Array ||
scope.discreteX)) {
barx = [];
scope.x.forEach(function(x, i) { barx.push(i + 1); });
}
if (scope.barMin && scope.barMax) {
scope.barWidths = scope.barMax.map(function(mx, i) {
return mx - scope.barMin[i];
});
var last = barx.length - 1;
scope.rangeXExtend = [barx[0] - scope.barMin[0],
scope.barMax[last] - barx[last]];
} else {
scope.barWidths = barx.map(function(xval, i) {
if (i == 0) return barx[1] - xval;
else if (i == barx.length - 1)
return xval - barx[barx.length - 2];
else return (barx[i+1] - barx[i-1]) / 2;
});
scope.rangeXExtend = [scope.barWidths[0] / 2,
scope.barWidths[barx.length - 1] / 2];
}
var width = scope.strokeWidth instanceof Array &&
scope.strokeWidth.length > 0 ?
scope.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(scope.strokeWidth) || 1);
scope.rangeExtendPixels([2*width, 2*width], null);
});
scope.$on('setupRanges', function(e, s) {
if (s.yrange) s.yrange[0] = 0;
else s.yrange = [0, null];
if (s.y2range) s.y2range[0] = 0;
else s.y2range = [0, null];
});
plotTypeLink('bars', scope, elm, as, draw);
}
};
}]);
// Box and whisker plots.
radian.directive('boxes',
['plotTypeLink', 'plotLib', function(plotTypeLink, lib)
{
'use strict';
function draw(svg, xin, xs, yin, ys, s, w, h) {
var x = xin, y = yin;
var strokeWidth = s.strokeWidth || 1;
var strokeOpacity = s.strokeOpacity || 1.0;
var stroke = s.stroke || '#000';
var fillOpacity = s.fillOpacity || 1.0;
var fill = s.fill || 'none';
var barWidth = s.barWidth || 0.5;
var pxBarWidth, pxWidth = false;
if (typeof barWidth == 'string' &&
barWidth.trim().substr(-2,2) == 'px') {
pxBarWidth =
Number(barWidth.trim().substr(0, barWidth.trim().length - 2));
barWidth = xs.invert(pxBarWidth) - xs.invert(0);
pxWidth = true;
}
// Data aggregation.
x = lib.unique(xin);
var q25 = lib.quantileBy(yin, xin, 0.25);
var q50 = lib.quantileBy(yin, xin, 0.5);
var q75 = lib.quantileBy(yin, xin, 0.75);
var qs = d3.zip(q25, q50, q75);
s.barWidths = lib.firstBy(s.barWidths, xin);
if (fill instanceof Array)
fill = lib.firstBy(fill, xin);
if (fillOpacity instanceof Array)
fillOpacity = lib.firstBy(fillOpacity, xin);
if (strokeWidth instanceof Array)
strokeWidth = lib.firstBy(strokeWidth, xin);
if (strokeOpacity instanceof Array)
strokeOpacity = lib.firstBy(strokeOpacity, xin);
if (stroke instanceof Array)
stroke = lib.firstBy(stroke, xin);
// Plot bars: plot attributes are either single values or arrays
// of values, one per bar.
function sty(v) {
return (v instanceof Array) ? function(d, i) { return v[i]; } : v;
};
var dat = d3.zip(x, qs);
svg.selectAll('rect').data(dat)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d, i) {
return xs(xs.oton(d[0]) -
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 2.0, i);
})
.attr('y', function(d, i) { return ys(d[1][2], i); })
.attr('width', function(d, i) {
if (pxWidth)
return pxBarWidth;
else
return xs(xs.oton(d[0]) + s.barWidths[i] * barWidth / 2.0, i) -
xs(xs.oton(d[0]) - s.barWidths[i] * barWidth / 2.0, i);
})
.attr('height', function(d, i) {
return ys(d[1][0], i) - ys(d[1][2], i);
})
.style('fill', sty(fill))
.style('fill-opacity', sty(fillOpacity))
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke));
svg.selectAll('line.median').data(dat).enter().append('line')
.attr('class', 'median')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.style('fill', 'none')
.attr('x1', function(d, i) {
return xs(xs.oton(d[0]) -
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 2.0, i);
})
.attr('x2', function(d, i) {
return xs(xs.oton(d[0]) +
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 2.0, i);
})
.attr('y1', function(d, i) { return ys(d[1][1], i); })
.attr('y2', function(d, i) { return ys(d[1][1], i); });
svg.selectAll('line.iqr-up').data(dat).enter().append('line')
.attr('class', 'iqr-up')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.style('fill', 'none')
.attr('x1', function(d, i) { return xs(xs.oton(d[0]), i); })
.attr('x2', function(d, i) { return xs(xs.oton(d[0]), i); })
.attr('y1', function(d, i) { return ys(d[1][2], i); })
.attr('y2', function(d, i) {
return ys(d[1][2] + 1.5 * (d[1][2] - d[1][0]), i);
});
svg.selectAll('line.iqr-up-bar').data(dat).enter().append('line')
.attr('class', 'iqr-up-bar')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.style('fill', 'none')
.attr('x1', function(d, i) {
return xs(xs.oton(d[0]) -
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 3.0, i);
})
.attr('x2', function(d, i) {
return xs(xs.oton(d[0]) +
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 3.0, i);
})
.attr('y1', function(d, i) {
return ys(d[1][2] + 1.5 * (d[1][2] - d[1][0]), i);
})
.attr('y2', function(d, i) {
return ys(d[1][2] + 1.5 * (d[1][2] - d[1][0]), i);
});
svg.selectAll('line.iqr-down').data(dat).enter().append('line')
.attr('class', 'iqr-down')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.style('fill', 'none')
.attr('x1', function(d, i) { return xs(xs.oton(d[0]), i); })
.attr('x2', function(d, i) { return xs(xs.oton(d[0]), i); })
.attr('y1', function(d, i) { return ys(d[1][0], i); })
.attr('y2', function(d, i) {
return ys(d[1][0] - 1.5 * (d[1][2] - d[1][0]), i);
});
svg.selectAll('line.iqr-down-bar').data(dat).enter().append('line')
.attr('class', 'iqr-down-bar')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.style('fill', 'none')
.attr('x1', function(d, i) {
return xs(xs.oton(d[0]) -
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 3.0, i);
})
.attr('x2', function(d, i) {
return xs(xs.oton(d[0]) +
(pxWidth ? barWidth : s.barWidths[i] * barWidth) / 3.0, i);
})
.attr('y1', function(d, i) {
return ys(d[1][0] - 1.5 * (d[1][2] - d[1][0]), i);
})
.attr('y2', function(d, i) {
return ys(d[1][0] - 1.5 * (d[1][2] - d[1][0]), i);
});
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.$on('setupExtra', function() {
var barx = scope.x || [];
// Discrete data.
if (scope.x && scope.x instanceof Array &&
(typeof scope.x[0] == 'string' ||
scope.x[0] instanceof Array ||
scope.discreteX)) {
barx = [];
scope.x.forEach(function(x, i) { barx.push(i + 1); });
}
scope.barWidths = barx.map(function(xval, i) {
if (i == 0) return barx[1] - xval;
else if (i == barx.length - 1)
return xval - barx[barx.length - 2];
else return (barx[i+1] - barx[i-1]) / 2;
});
scope.rangeXExtend = [scope.barWidths[0] / 2,
scope.barWidths[barx.length - 1] / 2];
var width = scope.strokeWidth instanceof Array &&
scope.strokeWidth.length > 0 ?
scope.strokeWidth.reduce(function(x,y) {
return Math.max(Number(x), Number(y));
}) : (Number(scope.strokeWidth) || 1);
scope.rangeExtendPixels([2*width, 2*width], [20, 20]);
});
plotTypeLink('boxes', scope, elm, as, draw);
}
};
}]);
// Area plots.
radian.directive('area',
['plotTypeLink', function(plotTypeLink)
{
'use strict';
function draw(svg, x, xs, y, ys, s, w, h, axis) {
var opacity = s.fillOpacity || 1.0;
var fill = s.fill || '#000';
var yminv = axis == 1 ? 'ymin' : 'y2min';
var xminv = axis == 1 ? 'xmin' : 'x2min';
var yarea = false, ymin, ymintmp = 0;
var xarea = false, xmin, xmintmp = 0;
if (s.hasOwnProperty(yminv)) {
ymintmp = s[yminv];
yarea = true;
if (ymintmp instanceof Array)
ymin = ymintmp;
else {
ymin = new Array(x.length);
for (var i = 0; i < ymin.length; ++i) ymin[i] = Number(ymintmp);
}
}
if (s.hasOwnProperty(xminv)) {
xmintmp = s[xminv];
xarea = true;
if (xmintmp instanceof Array)
xmin = xmintmp;
else {
xmin = new Array(y.length);
for (var i = 0; i < xmin.length; ++i) xmin[i] = Number(xmintmp);
}
}
if (!xarea && !yarea) throw Error("No ranges specified for <area>")
if (xarea && yarea) throw Error("Inconsistent ranges specified for <area>")
// Switch on type of stroke...
if (!(opacity instanceof Array || fill instanceof Array)) {
// Normal area; single path.
if (yarea) {
var area = d3.svg.area()
.x(function(d) { return xs.ap(d[0], i); })
.y0(function(d) { return ys(d[1], i); })
.y1(function(d) { return ys(d[2], i); });
svg.append('path').datum(d3.zip(x, ymin, y))
.attr('class', 'area').attr('d', area)
.style('fill-opacity', opacity)
.style('fill', fill);
} else {
var area = d3.svg.area()
.y(function(d) { return ys(d[2], i); })
.x0(function(d) { return xs.ap(d[0], i); })
.x1(function(d) { return xs.ap(d[1], i); });
svg.append('path').datum(d3.zip(xmin, x, y))
.attr('class', 'area').attr('d', area)
.style('fill-opacity', opacity)
.style('fill', fill);
}
} else throw Error("<area> plots require singular paint attributes")
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
plotTypeLink('area', scope, elm, as, draw);
}
};
}]);
// Rug plots.
radian.directive('rug',
['plotTypeLink', function(plotTypeLink)
{
'use strict';
function draw(svg, x, xs, y, ys, s) {
var stroke = s.stroke || '#000';
var strokeWidth = s.strokeWidth || 1.0;
var strokeOpacity = s.strokeOpacity || 1.0;
var tickLength = Number(s.tickLength || 5);
// Plot points: plot attributes are either single values or arrays
// of values, one per point.
function sty(v) {
return (v instanceof Array) ? function(d, i) { return v[i]; } : v;
};
var xrugs = [ ], yrugs = [ ], xr = xs.range(), yr = ys.range();
if (x) {
var y0 = ys.invert(yr[0]), y1 = ys.invert(yr[0] - tickLength);
xrugs = x.map(function(xval) { return [[xval, y0], [xval, y1]]; });
}
if (y) {
var x0 = xs.invert(xr[0]), x1 = xs.invert(xr[0] + tickLength);
yrugs = y.map(function(yval) { return [[x0, yval], [x1, yval]]; });
}
var rugs = xrugs.concat(yrugs);
svg.selectAll('path').data(rugs).enter().append('path')
.attr('class', 'line')
.style('stroke-width', sty(strokeWidth))
.style('stroke-opacity', sty(strokeOpacity))
.style('stroke', sty(stroke))
.attr('d', d3.svg.line()
.x(function (d, i) { return xs(d[0], i); })
.y(function (d, i) { return ys(d[1], i); }));
};
return {
restrict: 'E',
scope: true,
link: function(scope, elm, as) {
scope.checkPlottable = function(xvar, yvar) { return xvar || yvar; };
plotTypeLink('rug', scope, elm, as, draw);
}
};
}]);
// Process palette directive.
radian.directive('palette',
['processAttrs', 'radianEval', 'discPalFn', 'contPalFn',
function(processAttrs, radianEval, discPalFn, contPalFn)
{
'use strict';
return {
restrict: 'E',
scope: false,
link: function(scope, elm, attrs) {
// The <palette> element is only there to carry data, so hide it
// right away.
elm.hide();
// Process attributes.
processAttrs(scope, attrs);
if (!scope.name)
throw Error("<palette> directive without NAME attribute");
var name = scope.name;
var typ = scope.type || 'norm';
var interp = scope.interp || 'hsl';
interp = interp.toLowerCase();
var banded = scope.hasOwnProperty("banded");
// Process content -- all text children are appended together
// for parsing.
var paltext = '';
elm.contents().each(function(i,n) {
if (n instanceof Text) paltext += n.textContent;
});
// Normalise content: line separators are equivalent to
// semicolons.
paltext = radianEval(scope, paltext.trim());
paltext = paltext.replace(/\n/g, ';');
// Generate palette function.
var fn;
switch (typ) {
case 'discrete':
fn = discPalFn(paltext);
break;
case 'abs':
fn = contPalFn(true, paltext, banded, interp);
break;
case 'norm':
fn = contPalFn(false, paltext, banded, interp);
break;
default:
throw Error("invalid <palette> type: " + typ);
}
// Install palette function on nearest enclosing scope that
// isn't associated with an ng-repeat.
var s = scope;
while (s.$parent && s.hasOwnProperty('$index')) s = s.$parent;
s[name] = fn;
}
};
}]);
radian.factory('discPalFn', function()
{
// Mmmmmm... I love the smell of regular expressions in the
// morning. Smells like... VICTORY! Not.
var renoquotes = '[^"\\s]+', requotes = '"[^"]*"';
var reids = renoquotes + '|' + requotes;
var resplits = '(?:(' + reids + ')\\s+)?([^\\s;]+)';
var resings = '(?:(?:' + reids + ')\\s+)?(?:[^\\s;]+)';
var remults = '(' + resings + ')((?:\\s*;\\s*' + resings + ')*)';
var resplit = new RegExp(resplits);
var remult = new RegExp(remults);
var restripsemi = /\s*;\s*(.*)/;
return function(txt) {
// Prototype palette function for discrete palette with no keys,
// i.e. just a list of colours.
function protoNoKeys(n, cs, v) {
if (v instanceof Array) {
// For array data, we pull colours out of the palette in
// sorted order of the keys.
var vs = { };
v.forEach(function(x) { vs[x] = 1; });
var uvs = Object.keys(vs).sort();
return v.map(function(x) { return cs[uvs.indexOf(x) % n]; });
} else if (typeof v == "number")
// Otherwise, the palette function argument must be numeric
// and is just used as an index into the list of colours.
return cs[(Math.round(v) - 1) % n];
else throw Error("invalid operand to discrete palette function");
};
// Prototype palette function for discrete palette with keys.
function protoWithKeys(cs, v) {
// Just pull out the appropriate colour value using the key.
return (v instanceof Array) ?
v.map(function(x) { return cs[x]; }) : cs[v];
};
// Palette entries consist either of a key value or a key value
// and a colour, and are separated by semicolons. Key values may
// be quoted using double quotes.
txt = txt.trim();
var ks = [], cs = [], nks = 0, ms;
while (true) {
ms = txt.match(remult);
if (!ms) throw Error("invalid palette definition");
var m = ms[1];
var ss = m.match(resplit);
if (!ss) throw Error("invalid palette definition");
if (ss[1]) {
ks.push(ss[1].charAt(0) == '"' ? ss[1].slice(1, -1) : ss[1]);
++nks;
}
cs.push(ss[2]);
if (ms[2] == '') break;
var tmp = ms[2].match(restripsemi);
if (!tmp) throw Error("invalid palette definition");
txt = tmp[1];
}
// At this point, ks is an array of key values and cs is an array
// of colour values. If all the colours have keys, then we set up
// the key to colour mapping and return a function based on the
// "with keys" prototype. If none of the colours have keys, we
// return a function based on the "no keys" prototype. Any other
// situation is an error.
if (nks == 0) {
// Return a function based on the "no keys" prototype.
var thisn = cs.length;
var thiscs =
'[' + cs.map(function(c) { return '"' + c + '"' }).join(',') + ']';
return function(v) { return protoNoKeys(thisn, thiscs, v); };
} else if (nks == cs.length) {
// Return a function based on "with keys" prototype.
var thiscs = { };
for (var i = 0; i < cs.length; ++i) thiscs[ks[i]] = cs[i];
return function(v) { return protoWithKeys(thiscs, v); };
} else throw Error("invalid palette definition");
};
});
radian.factory('contPalFn', function()
{
return function(isabs, txt, band, interp) {
// Prototype for returned function for normalised palette -- does
// linear interpolation from data extent to [0,1] and applies
// polylinear colour interpolation function.
function protoNorm(cmap, v) {
if (!(v instanceof Array))
throw Error("normalised palettes must be applied to array arguments");
var ext = d3.extent(v);
var sc = d3.scale.linear().domain(ext);
return v.map(function(x) { return cmap(sc(x)); });
};
// Prototype for returned function for absolute palette -- just
// applies polylinear colour interpolation function.
function protoAbs(cmap, v) {
return v instanceof Array ?
v.map(function(x) { return cmap(x); }) : cmap(v);
};
// Set up appropriate D3 colour interpolation factory.
var intfac;
if (band)
intfac = function(a, b) { return function(t) { return a; }; };
else switch (interp) {
case 'rgb': intfac = d3.interpolateRgb; break;
case 'hcl': intfac = d3.interpolateHcl; break;
case 'lab': intfac = d3.interpolateLab; break;
default: intfac = d3.interpolateHsl; break;
}
// Palette entries are separated by semicolons: split them and
// trim them for further processing.
var cs = txt.split(';').
map(function(s) { return s.trim(); }).
filter(function(s) { return s.length > 0; });
// For normalised palettes, each entry should have a numeric value
// and a colour, separated by a space.
if (!cs.every(function(c) { return c.indexOf(' ') != -1; }))
throw Error("invalid format in <palette>");
// Extract the segment limits and colours from the palette data.
var lims = [], cols = [];
cs.forEach(function(x) {
var css = x.split(' ');
lims.push(Number(css[0].trim()));
cols.push(css[1].trim());
});
// Check for ascending limit values.
for (var i = 1; i < lims.length; ++i)
if (lims[i] < lims[i - 1])
throw Error("entries out of order in <palette>");
// Minimum and maximum segment limits (fix up top end for banded
// palettes).
var minl = lims[0], maxl = lims[lims.length-1];
if (band) {
if (isabs) {
lims.push(Number.MAX_VALUE);
cols.push('black');
maxl = Number.MAX_VALUE;
} else if (maxl != 1) {
lims.push(1);
cols.push('black');
maxl = 1;
}
}
if (!isabs && (minl != 0 || maxl != 1))
throw Error("invalid segment limits for normalised palette");
// Build polylinear colour interpolation scale using appropriate
// colour interpolation factory.
var thiscmap = d3.scale.linear().
clamp(true).interpolate(intfac).
domain(lims).range(cols);
return isabs ?
function(v) { return protoAbs(thiscmap, v); } :
function(v) { return protoNorm(thiscmap, v); };
};
});
radian.factory('genPalFn',
['discPalFn', 'contPalFn', 'MD5', 'plotLib',
function(discPalFn, contPalFn, MD5, plotLib)
{
'use strict';
return function(paldef) {
var paltext;
if (paldef.values)
paltext = d3.zip(paldef.values, paldef.colours).map(function(p) {
return p.join(' ');
}).join(';');
else
paltext = paldef.colours.join(';');
var fnname = paldef.type.charAt(0) + MD5(JSON.stringify(paltext));
if (!plotLib.rad$$pal[fnname]) {
var fn, interp = paldef.interp || 'hsl', band = paldef.banded;
switch (paldef.type) {
case 'discrete': fn = discPalFn(paltext); break;
case 'absolute': fn = contPalFn(true, paltext, band, interp); break;
case 'normalised': fn = contPalFn(false, paltext, band, interp); break;
}
plotLib.rad$$pal[fnname] = fn;
}
return fnname;
};
}]);
// Plotting function library.
radian.factory('plotLib', function()
{
'use strict';
// Vectorise scalar function.
function vect(f) {
return function(x) {
return (x instanceof Array) ? x.map(f) : f(x);
};
};
// Vectorise binary operator.
function vectOp(f) {
return function(x, y) {
var xa = x instanceof Array, ya = y instanceof Array;
if (!xa && !ya) return f(x, y);
var xlen = xa ? x.length : 0, ylen = ya ? y.length : 0;
var rlen = xa && ya ? Math.min(xlen, ylen) : Math.max(xlen, ylen);
var res = new Array(rlen);
var ff;
if (xa && ya) ff = function(i) { return f(x[i], y[i]); };
else if (xa) ff = function(i) { return f(x[i], y ); };
else ff = function(i) { return f(x, y[i]); };
for (var i = 0; i < rlen; ++i) res[i] = ff(i);
return res;
}
};
// Construct grouping function.
function by(f) {
return function(x, c) {
var cs = { }, ord = [];
x.forEach(function(e, i) {
if (cs[c[i]])
cs[c[i]].push(e);
else { ord.push(c[i]); cs[c[i]] = [e]; }
});
var ret = [];
ord.forEach(function(e) { ret.push(f(cs[e])); });
return ret;
};
};
// Basic functions.
function seq(s, e, n) { return d3.range(s, e, (e - s) / (n - 1)); };
function seqStep(s, e, delta) { return d3.range(s, e, delta); };
function sdev(x) {
var m = d3.mean(x), m2 = d3.mean(x, function(a) { return a*a; });
return Math.sqrt(m2 - m * m);
};
function unique(x) {
var ret = [], check = { };
x.forEach(function(e) { if (!check[e]) { ret.push(e); check[e] = 1; } });
return ret;
};
// log(Gamma(x))
function gammaln(x) {
function sum(xs) {
var s = 0;
xs.forEach(function(x) { s += x; });
return s;
}
var cof = [76.18009172947146,-86.50532032941677,24.01409824083091,
-1.231739572450155,0.001208650973866179,-0.000005395239384953];
var ser = 1.000000000190015;
var tmp = (x + 5.5) - (x + 0.5) * Math.log(x + 5.5);
var ser1 = ser + sum(cof.map(function(c,y) { return c/(x+y+1); }));
return (-tmp + Math.log(2.5066282746310005 * ser1 / x));
};
// Probability distributions.
function normal(x, mu, sigma) {
var c1 = 1 / (sigma * Math.sqrt(2 * Math.PI)), c2 = 2*sigma*sigma;
return vect(function(x) { return c1 * Math.exp(-(x-mu)*(x-mu)/c2); })(x);
};
function lognormal(x, mu, sigma) {
var c1 = 1 / (sigma * Math.sqrt(2 * Math.PI)), c2 = 2*sigma*sigma;
return vect(function(x) {
return x <= 0 ? 0 :
c1/x * Math.exp(-(Math.log(x)-mu)*(Math.log(x)-mu)/c2);
})(x);
};
function gamma(x, k, theta) {
var c = k * Math.log(theta) + gammaln(k);
return vect(function(x) {
return x <= 0 ? 0 : Math.exp((k - 1) * Math.log(x) - x / theta - c);
})(x);
};
function invgamma(x, alpha, beta) {
var c = alpha * Math.log(beta) - gammaln(alpha);
return vect(function(x) {
return x<=0 ? 0 : Math.exp(cval - beta / x - (alpha + 1) * Math.log(x));
})(x);
};
// Histogramming function.
function histogram(xs, opts) {
// Deal with special case where just the number of bins is given
// as an argument.
if (typeof opts == 'number' || typeof opts == 'string')
opts = { nbins: Number(opts) };
// Coordinate transforms: forwards.
function idfn(x) { return x; }
var hxs = xs, xform = null, xformname = null;
if (opts.hasOwnProperty('transform')) {
xform = opts.transform;
if (typeof xform == 'string') {
switch (xform) {
case 'linear':
xform = [idfn, idfn];
xformname = 'linear';
break;
case 'log':
xform = [Math.log, Math.exp];
xformname = 'log';
break;
default: throw Error("unknown coordinate transform in histogram");
}
}
if (!(xform instanceof Array && xform.length == 2))
throw Error("invalid coordinate transform in histogram");
hxs = xs.map(xform[0]);
}
// Bin width calculations. Performed in transformed coordinates.
var rng = d3.extent(hxs);
if (opts.hasOwnProperty('binrange')) {
rng = angular.copy(opts.binrange);
if (xformname == 'log') {
rng[0] = Math.log(rng[0]);
rng[1] = Math.log(rng[1]);
}
}
var binwidth = null, nbins = null;
if (opts.hasOwnProperty('nbins')) {
nbins = opts.nbins;
binwidth = (rng[1] - rng[0]) / nbins;
} else if (opts.hasOwnProperty('binwidth')) {
binwidth = opts.binwidth;
nbins = Math.floor((rng[1] - rng[0]) / binwidth);
}
// Calculate counts and frequencies per bin.
var ns = [], fs = [];
for (var i = 0; i < nbins; ++i) ns.push(0);
for (var i = 0; i < hxs.length; ++i)
++ns[Math.min(nbins-1, Math.max
(0, Math.floor((hxs[i] - rng[0]) / binwidth)))];
for (var i = 0; i < nbins; ++i) fs.push(ns[i] / hxs.length);
// Coordinate transforms: backwards (bin centres and extents).
var cs = [], bins = [], w2 = 0.5 * binwidth;
for (var i = 0; i < nbins; ++i) {
var c = rng[0] + binwidth * (i + 0.5);
var mn = c - w2, mx = c + w2;
if (xform) {
c = xform[1](c);
mn = xform[1](mn);
mx = xform[1](mx);
}
cs.push(c);
bins.push([mn, mx]);
}
// Calculate normalised probability values in input coordinates.
var tot = 0, ps = [];
for (var i = 0; i < nbins; ++i) tot += fs[i] * (bins[i][1] - bins[i][0]);
for (var i = 0; i < nbins; ++i) ps.push(fs[i] / tot);
var ret = { centres:cs, bins:bins, counts:ns, freqs:fs, probs:ps };
return ret;
};
// Helper function to find minimum and maximum values in a
// potentially nested array.
function flattenExtent(a) {
var min = Number.POSITIVE_INFINITY, max = Number.NEGATIVE_INFINITY;
for (var i = 0; i < a.length; ++i) {
if (a[i] instanceof Array) {
var sub = flattenExtent(a[i]);
min = Math.min(min, sub[0]); max = Math.max(max, sub[1]);
} else { min = Math.min(min, a[i]); max = Math.max(max, a[i]); }
}
return [min, max];
};
// Interpolator generating function.
function interpolate(d, r, t) {
var type = t || 'linear', base;
switch (type) {
case 'linear': base = d3.scale.linear(); break;
case 'sqrt': base = d3.scale.sqrt(); break;
case 'log': base = d3.scale.log(); break;
default:
if (type.substr(0, 4) == 'pow:')
base = d3.scale.pow().exponent(Number(type.substr(5)));
else throw Error("invalid interpolation type");
}
var dom = d || [0,1]; dom = flattenExtent(dom);
var rng = r || [0,1]; rng = flattenExtent(rng);
var ret = base.domain(dom).range(rng);
return function(x) { return x.map(ret); };
};
// Variadic array range function.
function multiExtent() {
if (arguments.length == 0) return [];
var ret = d3.extent(arguments[0]);
for (var i = 1; i < arguments.length; ++i) {
var e = d3.extent(arguments[i]);
ret = d3.extent([ret[0], ret[1], e[0], e[1]]);
}
return ret;
};
// Flatten arrays of arrays.
function flatten(a) {
if (a == undefined || !a) return a;
var ret = [];
function go(x) {
if (x instanceof Array)
x.forEach(go);
else
ret.push(x);
};
go(a);
return ret;
};
// Zip vectors together building composite categorical ordering
// metadata as required.
function metaDataAwareZip() {
var d = arguments;
var n = d.length;
if (!n) return [];
var m = d3.min(d, function(a) { return a.length; });
var zips = new Array(m);
for (var i = 0; i < m; ++i) {
zips[i] = new Array(n);
for (var j = 0; j < n; ++j) zips[i][j] = d[j][i];
}
function buildOrder(lev) {
var this_levels = [];
if (d[lev].metadata && d[lev].metadata.categoryOrder)
this_levels = d[lev].metadata.categoryOrder.split(/;/);
if (lev >= d.length - 1) return this_levels;
var next_levels = buildOrder(lev + 1);
var ret = [];
if (this_levels.length == 0)
next_levels.forEach(function(n) { ret.push(',' + n); });
else
this_levels.forEach(function(t) {
next_levels.forEach(function(n) { ret.push(t + ',' + n); });
});
return ret;
};
var do_order = false;
for (var i = 0; i < n; ++i)
if (d[i].metadata && d[i].metadata.categoryOrder) {
do_order = true;
break;
}
if (do_order)
zips.metadata = { categoryOrder: buildOrder(0).join(';') };
return zips;
};
// Perform simple ID plucking, pulling metadata out along the way.
function metaDataAwarePluck(obj, key) {
var ret = obj.map(function(x) { return x[key]; });
if (obj.metadata && obj.metadata[key])
ret.metadata = obj.metadata[key];
return ret;
};
// Calculate categorised quantiles.
function quantileBy(x, c, p) {
var cs = { }, ord = [];
x.forEach(function(e, i) {
if (cs[c[i]]) cs[c[i]].push(e);
else { ord.push(c[i]); cs[c[i]] = [e]; }
});
var ret = [];
ord.forEach(function(e) {
cs[e].sort();
ret.push(d3.quantile(cs[e], p));
});
return ret;
};
// Date conversion from strings.
function parseDate(d) { return new Date(d); };
// Library -- used for bringing useful names into scope for
// plotting data access expressions.
return { E: Math.E,
LN10: Math.LN10,
LN2: Math.LN2,
LOG10E: Math.LOG10E,
LOG2E: Math.LOG2E,
PI: Math.PI,
SQRT1_2: Math.SQRT1_2,
SQRT2: Math.SQRT2,
abs: vect(Math.abs),
acos: vect(Math.acos),
asin: vect(Math.asin),
atan: vect(Math.atan),
ceil: vect(Math.ceil),
cos: vect(Math.cos),
exp: vect(Math.exp),
floor: vect(Math.floor),
log: vect(Math.log),
round: vect(Math.round),
sin: vect(Math.sin),
sqrt: vect(Math.sqrt),
tan: vect(Math.tan),
atan2: Math.atan2,
pow: Math.pow,
min: d3.min,
max: d3.max,
extent: multiExtent,
flatten: flatten,
sum: d3.sum,
mean: d3.mean,
median: d3.median,
quantile: d3.quantile,
category10: vect(d3.scale.category10()),
category20: vect(d3.scale.category20()),
zip: metaDataAwareZip,
seq: seq,
seqStep: seqStep,
sdev: sdev,
unique: unique,
minBy: by(d3.min),
maxBy: by(d3.max),
sumBy: by(d3.sum),
meanBy: by(d3.mean),
medianBy: by(d3.median),
sdevBy: by(sdev),
firstBy: by(function(xs) { return xs[0]; }),
quantileBy: quantileBy,
normal: normal,
lognormal: lognormal,
gamma: gamma,
invgamma: invgamma,
histogram: histogram,
interpolate: interpolate,
parseDate: vect(parseDate),
rad$$neg: vect(function(a) { return -a; }),
rad$$add: vectOp(function(a, b) { return a + b; }),
rad$$sub: vectOp(function(a, b) { return a - b; }),
rad$$mul: vectOp(function(a, b) { return a * b; }),
rad$$div: vectOp(function(a, b) { return a / b; }),
rad$$pow: vectOp(function(a, b) { return Math.pow(a, b); }),
rad$$pluck: metaDataAwarePluck,
rad$$pal: {}
};
});
radian.factory('paintAttrsFromPlotType', [function() {
return function(t) {
switch (t) {
case 'lines': return ['stroke', 'strokeWidth', 'strokeOpacity' ];
case 'area': return ['fill', 'fillOpacity' ];
case 'points': return ['stroke', 'strokeWidth', 'strokeOpacity',
'fill', 'fillOpacity', 'marker' ];
case 'bars':
case 'boxes': return ['stroke', 'strokeWidth', 'strokeOpacity',
'fill', 'fillOpacity' ];
default: throw Error('invalid TYPE in <legend-entry>');
}
};
}]);
radian.directive('legend',
['processAttrs', 'dft', 'paintAttrsFromPlotType',
function(processAttrs, dft, paintAttrsFromPlotType)
{
function legendSizeAndPos(sc) {
// Get all size and position attributes.
var position = sc.position || 'left,top';
var posspl = position.split(/,/);
sc.posx = posspl[0];
sc.posy = posspl[1];
if (sc.posx == 'left') sc.posx = 10;
else if (sc.posx == 'right') sc.posx = -10;
if (sc.posy == 'top') sc.posy = 10;
else if (sc.posy == 'bottom') sc.posy = -10;
sc.posx = Number(sc.posx);
sc.posy = Number(sc.posy);
if (isNaN(sc.posx) || isNaN(sc.posy))
throw Error("invalid position for legend");
var orientation = sc.orientation || 'vertical';
var norientation = 1;
var orspl = orientation.split(/:/);
if (orspl.length > 1) {
orientation = orspl[0];
norientation = orspl[1];
}
sc.rowSpacing = sc.rowSpacing || 2;
sc.columnSpacing = sc.columnSpacing || 4;
sc.segmentLength = sc.segmentLength || 30;
sc.segmentGap = sc.segmentGap || 5;
sc.margin = sc.margin || 5;
sc.hmargin = sc.horizontalMargin || sc.margin;
sc.vmargin = sc.verticalMargin || sc.margin;
// Determine label text sizes.
sc.eh = 0;
sc.ew = 0;
sc.explicitEntries.forEach(function(e) {
var sz = sc.getTextSize(e.label);
e.width = sz.width; sc.ew = Math.max(sz.width, sc.ew);
e.height = sz.height; sc.eh = Math.max(sz.height, sc.eh);
});
sc.implicitEntries.forEach(function(e) {
var sz = sc.getTextSize(e.label);
e.width = sz.width; sc.ew = Math.max(sz.width, sc.ew);
e.height = sz.height; sc.eh = Math.max(sz.height, sc.eh);
});
sc.labelx = sc.segmentLength + sc.segmentGap;
sc.ew += sc.labelx;
// Add space for checkboxes if required.
var anyswitchable = sc.implicitEntries.some(function(e) {
return e.switchable;
});
if (anyswitchable) sc.ew += 15; // TODO: FIX SIZE!
// Order entries.
var order = [];
if (sc.order) order = sc.order.split(/\|/);
var ex = {}, im = {};
sc.explicitEntries.forEach(function(e) { ex[e.label] = e; });
sc.implicitEntries.forEach(function(e) { im[e.label] = e; });
sc.entries = [];
order.forEach(function(l) {
if (ex[l]) { sc.entries.push(ex[l]); delete ex[l]; }
else if (im[l]) { sc.entries.push(im[l]); delete im[l]; }
});
sc.implicitEntries.forEach(function(e) {
if (im[e.label]) sc.entries.push(e);
});
sc.explicitEntries.forEach(function(e) {
if (ex[e.label]) sc.entries.push(e);
});
// Allocate entries to rows/columns.
var major = orientation == 'vertical' ? 'col' : 'row';
var minor = orientation == 'vertical' ? 'row' : 'col';
var nentries = sc.entries.length;
var minorpermajor = Math.ceil(nentries / norientation);
var ientry = 0;
for (var imaj = 0; imaj < norientation; ++imaj)
for (var imin = 0; imin < minorpermajor && ientry < nentries; ++imin) {
sc.entries[ientry][major] = imaj;
sc.entries[ientry][minor] = imin;
++ientry;
}
var ncols = orientation == 'vertical' ? norientation : minorpermajor;
var nrows = orientation == 'vertical' ? minorpermajor : norientation;
sc.entries.forEach(function(e) {
e.inx = sc.hmargin + e.col * (sc.ew + sc.columnSpacing);
e.iny = sc.vmargin + e.row * (sc.eh + sc.rowSpacing);
});
sc.legw = ncols * sc.ew + (ncols - 1) * sc.columnSpacing + 2 * sc.hmargin;
sc.legh = nrows * sc.eh + (nrows - 1) * sc.rowSpacing + 2 * sc.vmargin;
};
function drawLegend(sc, plotgroup) {
// Remove any existing legend SVG group.
plotgroup.selectAll('.radian-legend').remove();
// Set up new legend group.
var lg = plotgroup.append('g').attr('class', 'radian-legend');
// Text size calculation function.
sc.getTextSize = function(t) {
var g = lg.append('g').attr('visibility', 'hidden');
var tstel = g.append('text').attr('x', 0).attr('y', 0)
.style('font-size', sc.fontSize + 'px').text(t);
var bbox = tstel[0][0].getBBox();
g.remove();
return bbox;
};
// Calculate legend size and position.
legendSizeAndPos(sc);
var lx = sc.posx >= 0 ? sc.posx :
sc.plotScope.views[0].realwidth + sc.posx - sc.legw;
var ly = sc.posy >= 0 ? sc.posy :
sc.plotScope.views[0].realheight + sc.posy - sc.legh;
lg.attr('transform', 'translate(' + lx + ',' + ly + ')');
// Draw background rectangle.
var bg = sc.backgroundColor || 'white';
if (bg != 'none')
lg.append('rect').
attr('height', sc.legh).attr('width', sc.legw).
attr('stroke', 'none').attr('fill', bg);
// Draw frame.
if (sc.hasOwnProperty('frameThickness') ||
sc.hasOwnProperty('frameColor')) {
var thickness = sc.frameThickness || 1;
var colour = sc.frameColor || 'black';
lg.append('rect').
attr('height', sc.legh).attr('width', sc.legw).
attr('stroke', colour).attr('stroke-thickness', thickness).
attr('fill', 'none');
}
sc.entries.forEach(function(e) {
// Make group for entry translated to appropriate position.
var eg = lg.append('g').attr('class', 'radian-legend-entry').
attr('transform', 'translate(' + e.inx + ',' + e.iny + ')');
// Draw entry label.
// eg.append('rect').attr('x', 0).attr('y', 0).
// attr('width', sc.ew).attr('height', sc.eh).attr('fill', '#DDD');
eg.append('text').attr('x', sc.labelx).attr('y', sc.eh/2).
style('dominant-baseline', 'middle').
style('font-size', sc.plotScope.fontSize + 'px').text(e.label);
// Draw entry segment.
switch (e.type) {
case 'lines':
eg.append('path').
datum([[0, sc.eh/2], [sc.segmentLength, sc.eh/2]]).
attr('d', d3.svg.line()).
style('stroke', e.stroke).
style('stroke-width', e.strokeWidth).
style('stroke-opacity', e.strokeOpacity || 1);
break;
case 'points':
eg.append('path').
attr('transform',
'translate(' + sc.segmentLength / 2 + ',' + sc.eh / 2 + ')').
attr('d', d3.svg.symbol().type(e.marker).size(0.75 * sc.eh * sc.eh)).
style('fill', e.fill || 'none').
style('fill-opacity', e.fillOpacity || 1).
style('stroke-width', e.strokeWidth || 1).
style('stroke-opacity', e.strokeOpacity || 1).
style('stroke', e.stroke || 'none');
break;
case 'area':
eg.append('rect').
attr('x', 0).attr('y', 0).
attr('width', sc.segmentLength).attr('height', sc.eh).
style('fill', e.fill).
style('fill-opacity', e.fillOpacity || 1);
break;
case 'bars':
case 'boxes':
eg.append('rect').
attr('x', sc.segmentLength / 2 - sc.eh / 2).attr('y', 0).
attr('width', sc.eh).attr('height', sc.eh).
style('stroke', e.stroke || 'none').
style('stroke-opacity', e.strokeOpacity || 1).
style('stroke-width', e.strokeWidth || 1).
style('fill', e.fill || 'none').
style('fill-opacity', e.fillOpacity || 1);
break;
}
});
sc.plotScope.$broadcast('legendLayoutComplete');
};
function preLink(sc, elm, as) {
sc.explicitEntries = [ ];
};
function postLink(sc, elm, as) {
processAttrs(sc, as);
sc.colour = function(v) {
var c = (v.stroke instanceof Array ? v.stroke[0] : v.stroke) || '#000';
return { color: c };
};
sc.$on('setupExtraAfter', function() {
var psc = sc;
while (psc.hasOwnProperty('$parent') && !psc.hasOwnProperty('addPlot'))
psc = psc.$parent;
sc.plotScope = psc;
var psw = psc.legendSwitches;
sc.implicitEntries = [ ];
dft(psc, function(s) {
var label = s.label;
if (!label && s.y && s.y.metadata &&
s.y.metadata.hasOwnProperty('label'))
label = s.y.metadata.label;
if (s.hasOwnProperty('plotType') && label) {
var attrs = paintAttrsFromPlotType(s.plotType);
var entry = { label: label, type: s.plotType,
switchable: s.hasOwnProperty('legendSwitch') || psw };
attrs.forEach(function(a) { if (s[a]) entry[a] = s[a]; });
s.legendEntry = entry;
s.legendScope = sc;
sc.implicitEntries.push(entry);
}
});
sc.plotScope.views[0].post = function(svg) { drawLegend(sc, svg); };
});
};
return {
restrict: 'E',
scope: true,
compile: function(elm, as, trans) {
return { pre: preLink, post: postLink };
},
};
}]);
radian.directive('legendEntry',
['paintAttrsFromPlotType',
function(paintAttrsFromPlotType)
{
'use strict';
return {
restrict: 'E',
scope: false,
link: function(sc, elm, as) {
// Identify the legend element.
if (!elm[0].parentNode || elm[0].parentNode.tagName != 'LEGEND')
throw Error('<legend-entry> not properly nested inside <legend>');
var legend = $(elm[0].parentNode);
// Copy metadata attributes into a new object.
if (!as.label) throw Error('<legend-entry> without LABEL attribute');
if (!as.type) throw Error('<legend-entry> without TYPE attribute');
var attrs = paintAttrsFromPlotType(as.type);
var entry = { label: as.label, type: as.type, switchable: false };
attrs.forEach(function(a) {
if (as.hasOwnProperty(a))
entry[a] = as[a];
else if (sc[a])
entry[a] = sc[a];
});
// Set up explicit entry in parent legend.
sc.explicitEntries.push(entry);
}
};
}]);
radian.directive('radianLegendSwitch', function()
{
return {
restrict: 'E',
template:
['<div class="radian-legend-switch">',
'<input ng-repeat="v in switchable" type="checkbox" ',
'ng-model="v.enabled" ng-change="$emit(\'paintChange\')">',
'</div>'].join(""),
replace: true,
scope: true,
link: function(sc, elm, as) {
sc.$on('legendLayoutComplete', function() {
var chs = $(elm).find(':checkbox');
sc.switchable.forEach(function(sw, i) {
var e = sw.legendEntry, lsc = sw.legendScope;
var y = sc.views[0].margin.top + lsc.posy + e.iny;
var x = sc.views[0].margin.left + lsc.posx + e.inx + lsc.ew - 10;
$(chs[i]).css('left', x+'px').css('top', y+'px');
});
});
}
};
});
radian.directive('radianAxisSwitch', function()
{
return {
restrict: 'E',
template:
['<div class="radian-axis-switch">',
'<button class="btn btn-mini" ng-click="switchState()">',
'{{axisName}} axis &rArr; {{label}}',
'</button>',
'</div>'].join(''),
replace: true,
scope: true,
link: function(scope, elm, as) {
var axis = as.axis || 'y';
scope.axisName = axis == 'y' ? 'Y' : 'X';
var uiattr = axis == 'y' ? 'uiAxisYTransform' : 'uiAxisXTransform';
var attr = axis == 'y' ? 'axisYTransform' : 'axisXTransform';
var type = scope[uiattr] || 'log';
scope.states = type.split(/,/);
if (scope.states.length == 1 && scope.states[0] != 'linear')
scope.states.unshift('linear');
for (var i = 0; i < scope.states.length; ++i)
if (['linear', 'log', 'linear-0'].indexOf(scope.states[i]) < 0)
throw Error("invalid UI axis switch type");
function setLabel() {
switch (scope.states[(scope.idx + 1) % scope.states.length]) {
case 'linear': scope.label = 'Linear'; break;
case 'log': scope.label = 'Log'; break;
case 'linear-0': scope.label = 'Linear (from 0)'; break;
}
};
scope.state = scope[attr] || scope.states[0];
scope.idx = Math.max(0, scope.states.indexOf(scope.state));
setLabel();
scope.$on('setupExtraAfter', function() {
var m = scope.views[0].margin;
if (axis == 'y')
elm.css('top', (m.top+3)+'px').css('left', (m.left+3)+'px');
else
elm.css('bottom', (m.bottom+3)+'px').css('right', (m.right+3)+'px');
});
scope.switchState = function() {
scope.idx = (scope.idx + 1) % scope.states.length;
scope.state = scope.states[scope.idx];
setLabel();
scope.$emit(axis == 'y' ? 'yAxisChange' : 'xAxisChange', scope.state);
};
}
};
});
radian.directive('radianStrokeSwitch', function()
{
return {
restrict: 'E',
template:
['<div class="radian-stroke-switch">',
'<div ng-show="swbut">',
'<span>{{swbutlab}}</span>',
'<button class="btn btn-mini" data-toggle="button" ',
'ng-click="$parent.strokesel=1-$parent.strokesel">',
'{{swbut}}',
'</button>',
'</div>',
'<div class="btn-group" ng-show="swsel">',
'<button class="btn btn-mini" ng-click="stepStroke()">',
'{{swsel[$parent.strokesel]}} &nbsp;&nbsp;&nbsp;&nbsp;&rArr;',
'</button>',
'</div>',
'</div>'].join(""),
replace: true,
scope: true,
link: function(scope, elm, as) {
if (!scope.strokeSwitch) return;
scope.$on('setupExtraAfter', function() {
var m = scope.views[0].margin;
elm.css('top', (m.top+3)+'px').css('right', (m.right+3)+'px');
});
scope.switches = scope.strokeSwitch.split(';');
scope.stepStroke = function() {
scope.$parent.strokesel =
(scope.$parent.strokesel + 1) % scope.switches.length;
};
var label = scope.strokeSwitchLabel;
if (scope.switches.length == 1) {
// On/off UI.
scope.swbut = scope.switches[0];
scope.swbutlab = label;
} else {
// Selector UI.
scope.swsel = scope.switches;
}
}
};
});
radian.directive('radianHistogramSwitch', function()
{
return {
restrict: 'E',
template:
['<div class="radian-histogram-switch btn-group">',
'<button class="btn btn-mini">',
'Bins: {{uiNBins}}',
'</button>',
'<button class="btn btn-mini" ng-click="dn(5)">',
'<strong>-5</strong>',
'</button>',
'<button class="btn btn-mini" ng-click="dn(1)">',
'-1',
'</button>',
'<button class="btn btn-mini" ng-click="up(1)">',
'+1',
'</button>',
'<button class="btn btn-mini" ng-click="up(5)">',
'<strong>+5</strong>',
'</button>',
'</div>'].join(""),
replace: true,
scope: true,
link: function(scope, elm, as) {
if (!scope.uiHistogramBins) return;
scope.$on('setupExtraAfter', function() {
var m = scope.views[0].margin;
elm.css('bottom', (m.bottom+3)+'px').css('left', (m.left+3)+'px');
});
scope.uiNBins = scope[scope.histogramBinsVar];
scope.$watch('histogramBinsVar', function(n, o) {
scope.uiNBins = scope[scope.histogramBinsVar];
});
scope.up = function(n) {
scope.uiNBins += n;
scope.$parent[scope.histogramBinsVar] = scope.uiNBins;
};
scope.dn = function(n) {
scope.uiNBins = Math.max(scope.uiNBins - n, 1);
scope.$parent[scope.histogramBinsVar] = scope.uiNBins;
};
}
};
});
// Depth-first traversal of Angular scopes. Much like Angular's
// scope.$broadcast capability, but with operations at each level
// driven by the caller, rather than an event receiver.
radian.factory('dft', function() {
'use strict';
return function(scope, f) {
function go(s) {
f(s);
for (var c = s.$$childHead; c; c = c.$$nextSibling) go(c);
};
go(scope);
};
});
// More flexible depth-first traversal of Angular scopes, allowing for
// pruning and skipping of the top level. The function f should
// return false if it doesn't want the traversal to continue into the
// current scope's children and true if it does.
radian.factory('dftEsc', function() {
'use strict';
return function(scope, f, dotop) {
function go(s, doit) {
if (doit) { if (!f(s)) return; }
for (var c = s.$$childHead; c; c = c.$$nextSibling) go(c, true);
};
go(scope, dotop);
};
});
// MD5 (Message-Digest Algorithm)
// http://www.webtoolkit.info/
radian.factory('MD5', function() {
return function (string) {
function RotateLeft(lValue, iShiftBits) {
return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
};
function AddUnsigned(lX,lY) {
var lX8 = lX & 0x80000000, lY8 = lY & 0x80000000;
var lX4 = lX & 0x40000000, lY4 = lY & 0x40000000;
var lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return lResult ^ 0x80000000 ^ lX8 ^ lY8;
if (lX4 | lY4) {
if (lResult & 0x40000000) return lResult ^ 0xC0000000 ^ lX8 ^ lY8;
else return lResult ^ 0x40000000 ^ lX8 ^ lY8;
} else return lResult ^ lX8 ^ lY8;
}
function F(x,y,z) { return (x & y) | ((~x) & z); }
function G(x,y,z) { return (x & z) | (y & (~z)); }
function H(x,y,z) { return (x ^ y ^ z); }
function I(x,y,z) { return (y ^ (x | (~z))); }
function FF(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function GG(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function HH(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function II(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function ConvertToWordArray(string) {
var wc, len = string.length;
var nw_temp1=len + 8, nw_temp2=(nw_temp1-(nw_temp1 % 64))/64;
var nw = (nw_temp2+1)*16;
var wa=Array(nw-1);
var bpos = 0, bc = 0;
while (bc < len) {
wc = (bc-(bc % 4))/4;
bpos = (bc % 4)*8;
wa[wc] = (wa[wc] | (string.charCodeAt(bc)<<bpos));
bc++;
}
wc = (bc-(bc % 4))/4;
bpos = (bc % 4)*8;
wa[wc] = wa[wc] | (0x80<<bpos);
wa[nw-2] = len<<3;
wa[nw-1] = len>>>29;
return wa;
};
function WordToHex(lValue) {
var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
for (lCount = 0;lCount<=3;lCount++) {
lByte = (lValue>>>(lCount*8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue +
WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
}
return WordToHexValue;
};
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) utftext += String.fromCharCode(c);
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
var x=Array();
var k,AA,BB,CC,DD,a,b,c,d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = Utf8Encode(string);
x = ConvertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k=0;k<x.length;k+=16) {
AA=a; BB=b; CC=c; DD=d;
a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
c=FF(c,d,a,b,x[k+2], S13,0x242070DB);b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
c=FF(c,d,a,b,x[k+6], S13,0xA8304613);b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
a=FF(a,b,c,d,x[k+8], S11,0x698098D8);d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
a=FF(a,b,c,d,x[k+12],S11,0x6B901122);d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
c=FF(c,d,a,b,x[k+14],S13,0xA679438E);b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);d=GG(d,a,b,c,x[k+10],S22,0x2441453);
c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
a=II(a,b,c,d,x[k+0], S41,0xF4292244);d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
a=II(a,b,c,d,x[k+12],S41,0x655B59C3);d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
c=II(c,d,a,b,x[k+6], S43,0xA3014314);b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
a=II(a,b,c,d,x[k+4], S41,0xF7537E82);d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
a=AddUnsigned(a,AA); b=AddUnsigned(b,BB);
c=AddUnsigned(c,CC); d=AddUnsigned(d,DD);
}
var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
return temp.toLowerCase();
};
});
// Dump tree of Angular scopes to console: useful for making sure that
// scopes have been set up properly in complicated transclusion cases.
radian.factory('dumpScope', function()
{
'use strict';
var go = function(scope, indent) {
var indentstr = "";
for (var i = 0; i < indent; ++i)
indentstr = indentstr.concat(" ");
console.log(indentstr + scope.$id + ": " +
Object.keys(scope).filter(function(k) {
return k.charAt(0) != "$" && k != "this";
}));
for (var ch = scope.$$childHead; ch; ch = ch.$$nextSibling)
go(ch, indent + 2);
};
return function(scope) { go(scope, 0); };
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment