From 61f2be55feceed990092c6fb33b6f317fc356742 Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk <2285135b@student.gla.ac.uk> Date: Tue, 7 Nov 2017 21:33:16 +0000 Subject: [PATCH] Init from given files --- .gitignore | 4 + .npmignore | 2 + LICENSE | 21 + README.md | 67 + ...3-force-neighbourSampling-papaparsing.html | 291 + examples/distribution_bar_graph.html | 110 + examples/js/distances/cosineSimilarity.js | 39 + examples/js/distances/diceDissimilarity.js | 28 + examples/js/distances/distance.js | 70 + examples/js/distances/distancePokerHands.js | 43 + examples/js/distances/euclideanDistance.js | 32 + .../js/distances/euclideanDistanceInTSNE.js | 33 + examples/js/distances/jaccardDissimilarity.js | 28 + examples/js/distances/manhattanDistance.js | 34 + examples/js/distances/normalization.js | 93 + examples/js/distances/numeric.js | 8 + examples/js/lib/d3.v4.js | 16866 ++++++++++++++++ examples/js/lib/d3.v4.min.js | 8 + examples/js/lib/intercom.js | 413 + examples/js/lib/intercom.min.js | 12 + examples/js/lib/jquery-3.1.1.js | 10220 ++++++++++ examples/js/lib/papaparse.js | 1403 ++ examples/js/lib/parallel.js | 390 + examples/js/src/interpolation.js | 195 + examples/js/src/interpolationPivots.js | 269 + ...ighbourSampling-papaparsing-nist-images.js | 579 + .../js/src/neighbourSampling-papaparsing.js | 656 + examples/js/src/pivotFinder.js | 109 + examples/nist-images.html | 274 + img/chalmers-fsmvis.PNG | Bin 0 -> 65759 bytes img/chalmers-poker.PNG | Bin 0 -> 187985 bytes index.js | 28 + package.json | 36 + src/barnesHut.js | 158 + src/constant.js | 8 + src/hybridSimulation.js | 154 + src/interpolation.js | 195 + src/interpolationPivots.js | 287 + src/jiggle.js | 6 + src/link.js | 150 + src/neighbourSampling.js | 257 + src/neighbourSamplingDistance.js | 300 + src/neighbourSamplingPre.js | 197 + src/t-sne.js | 374 + src/xy.js | 13 + 45 files changed, 34460 insertions(+) create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 examples/d3-force-neighbourSampling-papaparsing.html create mode 100644 examples/distribution_bar_graph.html create mode 100644 examples/js/distances/cosineSimilarity.js create mode 100644 examples/js/distances/diceDissimilarity.js create mode 100644 examples/js/distances/distance.js create mode 100644 examples/js/distances/distancePokerHands.js create mode 100644 examples/js/distances/euclideanDistance.js create mode 100644 examples/js/distances/euclideanDistanceInTSNE.js create mode 100644 examples/js/distances/jaccardDissimilarity.js create mode 100644 examples/js/distances/manhattanDistance.js create mode 100644 examples/js/distances/normalization.js create mode 100644 examples/js/distances/numeric.js create mode 100644 examples/js/lib/d3.v4.js create mode 100644 examples/js/lib/d3.v4.min.js create mode 100644 examples/js/lib/intercom.js create mode 100644 examples/js/lib/intercom.min.js create mode 100644 examples/js/lib/jquery-3.1.1.js create mode 100644 examples/js/lib/papaparse.js create mode 100644 examples/js/lib/parallel.js create mode 100644 examples/js/src/interpolation.js create mode 100644 examples/js/src/interpolationPivots.js create mode 100644 examples/js/src/neighbourSampling-papaparsing-nist-images.js create mode 100644 examples/js/src/neighbourSampling-papaparsing.js create mode 100644 examples/js/src/pivotFinder.js create mode 100644 examples/nist-images.html create mode 100644 img/chalmers-fsmvis.PNG create mode 100644 img/chalmers-poker.PNG create mode 100644 index.js create mode 100644 package.json create mode 100644 src/barnesHut.js create mode 100644 src/constant.js create mode 100644 src/hybridSimulation.js create mode 100644 src/interpolation.js create mode 100644 src/interpolationPivots.js create mode 100644 src/jiggle.js create mode 100644 src/link.js create mode 100644 src/neighbourSampling.js create mode 100644 src/neighbourSamplingDistance.js create mode 100644 src/neighbourSamplingPre.js create mode 100644 src/t-sne.js create mode 100644 src/xy.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e790593 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +build/ +node_modules +npm-debug.log diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..6e6b220 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +build/*.zip +test/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a1c0f39 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Remigijus Bartasius, Matthew Chalmers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc006cf --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# d3-neighbour-sampling + +This module implements Chalmers' 1996 Neighbour and Sampling algorithm for drawing the force-directed layouts. It is a linear time algorithm that uses stochastic sampling to find the best neighbours for high-dimensional data and creates the layout in 2 dimensions. + +Neighbour and Sampling algorithm is useful for producing visualizations that show relationships between the data. For instance: + +![fsmvis data set](https://raw.githubusercontent.com/sReeper/d3-neighbour-sampling/master/img/chalmers-fsmvis.PNG)![Poker Hands data set](https://raw.githubusercontent.com/sReeper/d3-neighbour-sampling/master/img/chalmers-poker.PNG) + +### Authors +Remigijus Bartasius and Matthew Chalmers + +### Reference +- Chalmers, Matthew. ["A linear iteration time layout algorithm for visualising high-dimensional data."](http://dl.acm.org/citation.cfm?id=245035) Proceedings of the 7th conference on Visualization'96. IEEE Computer Society Press, 1996. + +## Installing + +Download the [latest release](https://github.com/sReeper/d3-neighbour-sampling/releases/latest). + +## API Reference + +#### NeighbourSampling + +The Neighbour and Sampling algorithm tries to group the nodes based on the distance between them. If the nodes have a low distance, then the force attracts them to each other. If the nodes have a high distance, then the repulsive force pushes them further apart from each other. + +In order for it to work properly, a distance function should be specified. + +# d3.forceNeighbourSampling() [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js "Source") + +Initializes the Neighbour and Sampling algorithm with default parameters. + +# neighbourSampling.id([id]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L218 "Source") + +If *id* is specified, sets the node id accessor to the specified function and returns this force. If *id* is not specified, returns the current node id accessor, which defaults to the numeric *node*.index: + +```js +function id(d) { + return d.index; +} +``` + +The id accessor is invoked for each node whenever the force is initialized, as when the nodes change, being passed the node and its zero-based index. + +# neighbourSampling.distance([distance]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L230 "Source") + +If *distance* is specified, sets the distance accessor to the specified number or function, re-evaluates the distance accessor for each link, and returns this force. If *distance* is not specified, returns the current distance accessor, which defaults to: + +```js +function distance() { + return 300; +} +``` + +# neighbourSampling.neighbourSize([neighbourSize]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L222 "Source") + +If *neighbourSize* is specified, sets the neighbour set size to the specified number and returns this force. If *neighbourSize* is not specified, returns the current value, which defaults to 6. + +# neighbourSampling.sampleSize([sampleSize]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L226 "Source") + +If *sampleSize* is specified, sets the sample set size to the specified number and returns this force. If *sampleSize* is not specified, returns the current value, which defaults to 3. + +# neighbourSampling.stress() [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L234 "Source") + +Returns the stress of the layout. + +# neighbourSampling.velocity() [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L238 "Source") + +Returns the average velocity of the iteration. \ No newline at end of file diff --git a/examples/d3-force-neighbourSampling-papaparsing.html b/examples/d3-force-neighbourSampling-papaparsing.html new file mode 100644 index 0000000..77760d0 --- /dev/null +++ b/examples/d3-force-neighbourSampling-papaparsing.html @@ -0,0 +1,291 @@ + + + + + + +

Evaluation

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + +
+
+ +
+

Select algorithm:

+
+ Hybrid + layout +
+ + + Neighbour + and Sampling
+ + Link + force in D3
+ Barnes-Hut
+ t-SNE
+ +
+
+ +
+

Select distance function:

+
+ General
+ Euclidean
+ Manhattan
+ Jaccard
+ Dice
+ Cosine
+ Poker Hands
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/distribution_bar_graph.html b/examples/distribution_bar_graph.html new file mode 100644 index 0000000..016efb6 --- /dev/null +++ b/examples/distribution_bar_graph.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/js/distances/cosineSimilarity.js b/examples/js/distances/cosineSimilarity.js new file mode 100644 index 0000000..f3ac4c9 --- /dev/null +++ b/examples/js/distances/cosineSimilarity.js @@ -0,0 +1,39 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateCosineSimilarity(source, target, properties, normArgs) { + var numerator = 0.0; + + // console.log(properties); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (property.toLowerCase() !== "class" && property.toLowerCase() !== "app" && property.toLowerCase() !== "user" && property.toLowerCase() !== "weekday") { + var s = source[property], + t = target[property]; + + numerator += s * t; + } + } + + let denominator = squareRooted(source, properties, normArgs) * squareRooted(target, properties, normArgs); + + // console.log(Math.abs(numerator / denominator)); + return Math.abs(numerator / denominator); +} + +function squareRooted(node, properties, normArgs) { + var sum = 0.0; + + for (var i = 0, s; i < properties.length; i++) { + var s = node[properties[i]]; + + sum += s * s; + } + + return Math.sqrt(sum); +} diff --git a/examples/js/distances/diceDissimilarity.js b/examples/js/distances/diceDissimilarity.js new file mode 100644 index 0000000..9bcc29e --- /dev/null +++ b/examples/js/distances/diceDissimilarity.js @@ -0,0 +1,28 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateDiceDissimilarity(source, target, properties, normArgs) { + var notShared = 0.0; + + // console.log(properties); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (property.toLowerCase() !== "class" && property.toLowerCase() !== "app" && property.toLowerCase() !== "user" && property.toLowerCase() !== "weekday") { + var s = source[property], + t = target[property]; + + if (s !== t) { + notShared++; + } + } + } + + // console.log(Math.sqrt(sumDiff)/cols); + // console.log(cols); + return notShared / (notShared + 2 * (properties.length - notShared)); +} diff --git a/examples/js/distances/distance.js b/examples/js/distances/distance.js new file mode 100644 index 0000000..592416f --- /dev/null +++ b/examples/js/distances/distance.js @@ -0,0 +1,70 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @param {object} normArgs - the normalization arguments. + * @return {number} the distance between source and target nodes. + */ +function calculateDistance(source, target, properties, normArgs) { + var val1 = 0.0, val2 = 0.0, + sumDiff = 0.0, + ordDiff = 1.0, + ORD_FACTOR = 0.75, + cols = 0, + average = normArgs.avg, + sigma = normArgs.sig, + st_dev = normArgs.st_d; + + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (source.hasOwnProperty(property) && target.hasOwnProperty(property) + && property.toLowerCase() !== "index" ) { + var s = source[property], + t = target[property]; + + // Comparing Floats and Integers + if ((isNumeric(s) && isNumeric(t))) { + val1 = parseFloat(s); + val2 = parseFloat(t); + if (sigma[i] != 0) { + val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]); + val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]); + } + sumDiff += (val1-val2) * (val1-val2); + cols++; + // Comparing strings + } else if (/[a-zA-Z]/.test(s) && /[a-zA-Z]/.test(t) && s === t) { + ordDiff *= ORD_FACTOR; + cols++; + } else { + // Comparing Dates + var parsedDateS = Date.parse(s); + var parsedDateT = Date.parse(t); + if (isNaN(s) && !isNaN(parsedDateS) + && isNaN(t) && !isNaN(parsedDateT)) { + + val1 = parsedDateS.valueOf(), + val2 = parsedDateT.valueOf(); + + if (sigma[i] !== 0) { + val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]); + val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]); + } + sumDiff += (val1-val2) * (val1-val2); + cols++; + } + } + } + } + sumDiff = Math.sqrt(sumDiff); + sumDiff *= ordDiff; + + if (cols > 0) { + sumDiff *= properties.length/cols; + } + + console.log(sumDiff); + return sumDiff; +} \ No newline at end of file diff --git a/examples/js/distances/distancePokerHands.js b/examples/js/distances/distancePokerHands.js new file mode 100644 index 0000000..03fa544 --- /dev/null +++ b/examples/js/distances/distancePokerHands.js @@ -0,0 +1,43 @@ +/** + * The distance function that is specifically made for Poker Hands data set. + * The suit of the cards does not play an important role when finding + * the differences in poker hands so it was not used in calculations. + * @param {node} source + * @param {node} target + * @return {number} the distance between source and target nodes. + */ +function calculateDistancePoker(source, target) { + var sumDiff = 0.0, + ordDiff = 1.0, + ORD_FACTOR = 1.5, + cards = ["C1", "C2", "C3", "C4", "C5"], + cols = 0; + + // Iterate through cards + for (var i = 0; i < cards.length; i++) { + card = cards[i]; + if (source.hasOwnProperty(card) && target.hasOwnProperty(card)) { + var s = parseInt(source[card]), + t = parseInt(target[card]); + // Calculate the squared difference. + sumDiff += (s-t) * (s-t); + } + } + + // Class of poker hands describes the similarities the best + // so give it more priority than checking the differences between cards. + if (source.hasOwnProperty("CLASS") && target.hasOwnProperty("CLASS")) { + var s = parseInt(source["CLASS"]), + t = parseInt(target["CLASS"]); + + // If classes differ, then scale them by a factor. + if (s !== t) { + ordDiff *= (ORD_FACTOR * (Math.abs(s-t))) + } + } + + sumDiff = Math.sqrt(sumDiff); + sumDiff *= ordDiff; + + return sumDiff; +} \ No newline at end of file diff --git a/examples/js/distances/euclideanDistance.js b/examples/js/distances/euclideanDistance.js new file mode 100644 index 0000000..f274cc2 --- /dev/null +++ b/examples/js/distances/euclideanDistance.js @@ -0,0 +1,32 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateEuclideanDistance(source, target, properties, normArgs) { + var sumDiff = 0.0; + + // console.log(normArgs); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (property.toLowerCase() !== "class" && property.toLowerCase() !== "app" && property.toLowerCase() !== "user" && property.toLowerCase() !== "weekday") { + var s = source[property], + t = target[property]; + + if (normArgs.sig[i] !== 0) { + s = (s - normArgs.avg[i]) / (2.0 * normArgs.sig[i]); + t = (t - normArgs.avg[i]) / (2.0 * normArgs.sig[i]); + } + sumDiff += (s - t) * (s - t); + } + } + + // console.log(Math.sqrt(sumDiff)/cols); + // console.log(cols); + // sumDiff = Math.sqrt(sumDiff); + // console.log(sumDiff); + return Math.sqrt(sumDiff); +} diff --git a/examples/js/distances/euclideanDistanceInTSNE.js b/examples/js/distances/euclideanDistanceInTSNE.js new file mode 100644 index 0000000..ee90d81 --- /dev/null +++ b/examples/js/distances/euclideanDistanceInTSNE.js @@ -0,0 +1,33 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateEuclideanDistanceTSNE(source, target, properties, normArgs) { + var dotProduct = 0.0, + sumX = 0.0, + sumY = 0.0; + + // console.log(normArgs); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (source.hasOwnProperty(property) && target.hasOwnProperty(property) && + property.toLowerCase() !== "class") { + var s = source[property], + t = target[property]; + + dotProduct += s * t; + + sumX += s * s; + sumY += t * t; + } + } + + // console.log("Dot", dotProduct); + // console.log((-2 * dotProduct) + sumX + sumY); + + return -2 * dotProduct + sumX + sumY; +} diff --git a/examples/js/distances/jaccardDissimilarity.js b/examples/js/distances/jaccardDissimilarity.js new file mode 100644 index 0000000..1f55dfe --- /dev/null +++ b/examples/js/distances/jaccardDissimilarity.js @@ -0,0 +1,28 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateJaccardDissimilarity(source, target, properties, normArgs) { + var notShared = 0.0; + + // console.log(properties); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (property.toLowerCase() !== "class" && property.toLowerCase() !== "app" && property.toLowerCase() !== "user" && property.toLowerCase() !== "weekday") { + var s = source[property], + t = target[property]; + + if (s !== t) { + notShared++; + } + } + } + + // console.log(Math.sqrt(sumDiff)/cols); + // console.log(cols); + return notShared / properties.length; +} diff --git a/examples/js/distances/manhattanDistance.js b/examples/js/distances/manhattanDistance.js new file mode 100644 index 0000000..eca99dc --- /dev/null +++ b/examples/js/distances/manhattanDistance.js @@ -0,0 +1,34 @@ +/** + * Calculate the distances by using the numbers, strings and dates. + * @param {node} source + * @param {node} target + * @param {array} properties - the properties of the nodes. + * @return {number} the distance between source and target nodes. + */ +function calculateManhattanDistance(source, target, properties, normArgs) { + var sum = 0.0, + cols = 0; + + // console.log(properties); + // Iterate through every column of data + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + if (property.toLowerCase() !== "class" && property.toLowerCase() !== "app" && property.toLowerCase() !== "user" && property.toLowerCase() !== "weekday") { + var s = source[property], + t = target[property]; + + if (s !== t) { + cols++; + } + + if (normArgs.sig[i] !== 0) { + s = (s - normArgs.avg[i]) / (2.0 * normArgs.sig[i]); + t = (t - normArgs.avg[i]) / (2.0 * normArgs.sig[i]); + } + sum += Math.abs(s - t); + } + } + + // console.log(Math.sqrt(sumDiff)/cols); + return sum * (cols / properties.length); +} diff --git a/examples/js/distances/normalization.js b/examples/js/distances/normalization.js new file mode 100644 index 0000000..6f6cea5 --- /dev/null +++ b/examples/js/distances/normalization.js @@ -0,0 +1,93 @@ +/** + * Calculate the values that are used for normalizing the data. + * @param {array} nodes + * @return {object} that contains the normalization parameters. + */ +function calculateNormalization(nodes) { + var STANDARD_DEV = 2.0, + properties = Object.keys(nodes[0]), + sums = calculateSums(nodes, properties), + average = [], + sigma = []; + + // For each property, calculate mean and sigma. + for (var i = 0; i < properties.length; i++) { + var avg = sums.sumOfVal[i] / nodes.length; + average[i] = avg; + sigma[i] = Math.sqrt((sums.sumOfSq[i] - (nodes.length * Math.pow(avg, 2))) / nodes.length); + } + return { + avg: average, + sig: sigma, + st_d: standardDevation(nodes, properties, average) + }; +} + + +function standardDevation(nodes, properties, avg) { + + var stDev = new Array(properties.length).fill(0) + + for (var i = 0; i < properties.length; i++) { + var sum = 0; + + nodes.forEach(function (node) { + var val = node[properties[i]]; + var parsedDate = Date.parse(val); + var propAvg = avg[i]; + + if (isNaN(val) && !isNaN(parsedDate)) { + val = parsedDate.valueOf(); + } else if (isNumeric(val)) { + val = parseFloat(val); + // Ignore the strings. + } else { + val = 0; + } + + sum += Math.pow(val - propAvg, 2); + }); + + stDev[i] = Math.sqrt(sum/nodes.length); + } + + return stDev; + +} + +// Calculate the sum of values and the squared sum +/** + * Calculate the sums of each property. + * @param {array} nodes + * @param {array} properties - list of properties + * @return {object} that contains arrays with sum of values + * and the squared sums. + */ +function calculateSums(nodes, properties) { + var sumOfValues = new Array(properties.length).fill(0), + sumOfSquares = new Array(properties.length).fill(0); + + // Calculate the sums for each node. + nodes.forEach(function (node) { + for (var i = 0; i < properties.length; i++) { + var val = node[properties[i]]; + var parsedDate = Date.parse(val); + + if (isNaN(val) && !isNaN(parsedDate)) { + sumOfValues[i] += parsedDate.valueOf(); + sumOfSquares[i] += Math.pow(parsedDate.valueOf(), 2); + } else if (isNumeric(val)) { + sumOfValues[i] += parseFloat(val); + sumOfSquares[i] += Math.pow(parseFloat(val), 2); + // Ignore the strings. + } else { + sumOfValues[i] += 0; + sumOfSquares[i] += 0; + } + } + }); + return { + sumOfVal: sumOfValues, + sumOfSq: sumOfSquares + }; +} \ No newline at end of file diff --git a/examples/js/distances/numeric.js b/examples/js/distances/numeric.js new file mode 100644 index 0000000..6cc76cc --- /dev/null +++ b/examples/js/distances/numeric.js @@ -0,0 +1,8 @@ +/** + * Check if the object (string, number, etc.) contains a number. + * @param {object} n - object to check. + * @return {Boolean} true, if it is a number, false otherwise. + */ +function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} \ No newline at end of file diff --git a/examples/js/lib/d3.v4.js b/examples/js/lib/d3.v4.js new file mode 100644 index 0000000..2c4aa86 --- /dev/null +++ b/examples/js/lib/d3.v4.js @@ -0,0 +1,16866 @@ +// https://d3js.org Version 4.9.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var version = "4.9.1"; + +var ascending = function(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +}; + +var bisector = function(compare) { + if (compare.length === 1) compare = ascendingComparator(compare); + return { + left: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; + else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; + else lo = mid + 1; + } + return lo; + } + }; +}; + +function ascendingComparator(f) { + return function(d, x) { + return ascending(f(d), x); + }; +} + +var ascendingBisect = bisector(ascending); +var bisectRight = ascendingBisect.right; +var bisectLeft = ascendingBisect.left; + +var pairs = function(array, f) { + if (f == null) f = pair; + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = f(p, p = array[++i]); + return pairs; +}; + +function pair(a, b) { + return [a, b]; +} + +var cross = function(values0, values1, reduce) { + var n0 = values0.length, + n1 = values1.length, + values = new Array(n0 * n1), + i0, + i1, + i, + value0; + + if (reduce == null) reduce = pair; + + for (i0 = i = 0; i0 < n0; ++i0) { + for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { + values[i] = reduce(value0, values1[i1]); + } + } + + return values; +}; + +var descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var number = function(x) { + return x === null ? NaN : +x; +}; + +var variance = function(values, valueof) { + var n = values.length, + m = 0, + i = -1, + mean = 0, + value, + delta, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + if (m > 1) return sum / (m - 1); +}; + +var deviation = function(array, f) { + var v = variance(array, f); + return v ? Math.sqrt(v) : v; +}; + +var extent = function(values, valueof) { + var n = values.length, + i = -1, + value, + min, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + return [min, max]; +}; + +var array = Array.prototype; + +var slice = array.slice; +var map = array.map; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var identity = function(x) { + return x; +}; + +var sequence = function(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; +}; + +var e10 = Math.sqrt(50); +var e5 = Math.sqrt(10); +var e2 = Math.sqrt(2); + +var ticks = function(start, stop, count) { + var reverse = stop < start, + i = -1, + n, + ticks, + step; + + if (reverse) n = start, start = stop, stop = n; + + if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; + + if (step > 0) { + start = Math.ceil(start / step); + stop = Math.floor(stop / step); + ticks = new Array(n = Math.ceil(stop - start + 1)); + while (++i < n) ticks[i] = (start + i) * step; + } else { + start = Math.floor(start * step); + stop = Math.ceil(stop * step); + ticks = new Array(n = Math.ceil(start - stop + 1)); + while (++i < n) ticks[i] = (start - i) / step; + } + + if (reverse) ticks.reverse(); + + return ticks; +}; + +function tickIncrement(start, stop, count) { + var step = (stop - start) / Math.max(0, count), + power = Math.floor(Math.log(step) / Math.LN10), + error = step / Math.pow(10, power); + return power >= 0 + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) + : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); +} + +function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) step1 *= 10; + else if (error >= e5) step1 *= 5; + else if (error >= e2) step1 *= 2; + return stop < start ? -step1 : step1; +} + +var sturges = function(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; +}; + +var histogram = function() { + var value = identity, + domain = extent, + threshold = sturges; + + function histogram(data) { + var i, + n = data.length, + x, + values = new Array(n); + + for (i = 0; i < n; ++i) { + values[i] = value(data[i], i, data); + } + + var xz = domain(values), + x0 = xz[0], + x1 = xz[1], + tz = threshold(values, x0, x1); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + tz = tickStep(x0, x1, tz); + tz = sequence(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive + } + + // Remove any thresholds outside the domain. + var m = tz.length; + while (tz[0] <= x0) tz.shift(), --m; + while (tz[m - 1] > x1) tz.pop(), --m; + + var bins = new Array(m + 1), + bin; + + // Initialize bins. + for (i = 0; i <= m; ++i) { + bin = bins[i] = []; + bin.x0 = i > 0 ? tz[i - 1] : x0; + bin.x1 = i < m ? tz[i] : x1; + } + + // Assign data to bins by value, ignoring any outside the domain. + for (i = 0; i < n; ++i) { + x = values[i]; + if (x0 <= x && x <= x1) { + bins[bisectRight(tz, x, 0, m)].push(data[i]); + } + } + + return bins; + } + + histogram.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; + }; + + histogram.domain = function(_) { + return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; + }; + + histogram.thresholds = function(_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; + }; + + return histogram; +}; + +var threshold = function(values, p, valueof) { + if (valueof == null) valueof = number; + if (!(n = values.length)) return; + if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); + if (p >= 1) return +valueof(values[n - 1], n - 1, values); + var n, + i = (n - 1) * p, + i0 = Math.floor(i), + value0 = +valueof(values[i0], i0, values), + value1 = +valueof(values[i0 + 1], i0 + 1, values); + return value0 + (value1 - value0) * (i - i0); +}; + +var freedmanDiaconis = function(values, min, max) { + values = map.call(values, number).sort(ascending); + return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3))); +}; + +var scott = function(values, min, max) { + return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); +}; + +var max = function(values, valueof) { + var n = values.length, + i = -1, + value, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && value > max) { + max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && value > max) { + max = value; + } + } + } + } + } + + return max; +}; + +var mean = function(values, valueof) { + var n = values.length, + m = n, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) sum += value; + else --m; + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; + else --m; + } + } + + if (m) return sum / m; +}; + +var median = function(values, valueof) { + var n = values.length, + i = -1, + value, + numbers = []; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + numbers.push(value); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + numbers.push(value); + } + } + } + + return threshold(numbers.sort(ascending), 0.5); +}; + +var merge = function(arrays) { + var n = arrays.length, + m, + i = -1, + j = 0, + merged, + array; + + while (++i < n) j += arrays[i].length; + merged = new Array(j); + + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + + return merged; +}; + +var min = function(values, valueof) { + var n = values.length, + i = -1, + value, + min; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && min > value) { + min = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && min > value) { + min = value; + } + } + } + } + } + + return min; +}; + +var permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; +}; + +var scan = function(values, compare) { + if (!(n = values.length)) return; + var n, + i = 0, + j = 0, + xi, + xj = values[j]; + + if (compare == null) compare = ascending; + + while (++i < n) { + if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { + xj = xi, j = i; + } + } + + if (compare(xj, xj) === 0) return j; +}; + +var shuffle = function(array, i0, i1) { + var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0]; + array[m + i0] = array[i + i0]; + array[i + i0] = t; + } + + return array; +}; + +var sum = function(values, valueof) { + var n = values.length, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (value = +values[i]) sum += value; // Note: zero and null are equivalent. + } + } + + else { + while (++i < n) { + if (value = +valueof(values[i], i, values)) sum += value; + } + } + + return sum; +}; + +var transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { + row[j] = matrix[j][i]; + } + } + return transpose; +}; + +function length(d) { + return d.length; +} + +var zip = function() { + return transpose(arguments); +}; + +var slice$1 = Array.prototype.slice; + +var identity$1 = function(x) { + return x; +}; + +var top = 1; +var right = 2; +var bottom = 3; +var left = 4; +var epsilon = 1e-6; + +function translateX(x) { + return "translate(" + (x + 0.5) + ",0)"; +} + +function translateY(y) { + return "translate(0," + (y + 0.5) + ")"; +} + +function center(scale) { + var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. + if (scale.round()) offset = Math.round(offset); + return function(d) { + return scale(d) + offset; + }; +} + +function entering() { + return !this.__axis; +} + +function axis(orient, scale) { + var tickArguments = [], + tickValues = null, + tickFormat = null, + tickSizeInner = 6, + tickSizeOuter = 6, + tickPadding = 3, + k = orient === top || orient === left ? -1 : 1, + x = orient === left || orient === right ? "x" : "y", + transform = orient === top || orient === bottom ? translateX : translateY; + + function axis(context) { + var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, + format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat, + spacing = Math.max(tickSizeInner, 0) + tickPadding, + range = scale.range(), + range0 = range[0] + 0.5, + range1 = range[range.length - 1] + 0.5, + position = (scale.bandwidth ? center : identity$1)(scale.copy()), + selection = context.selection ? context.selection() : context, + path = selection.selectAll(".domain").data([null]), + tick = selection.selectAll(".tick").data(values, scale).order(), + tickExit = tick.exit(), + tickEnter = tick.enter().append("g").attr("class", "tick"), + line = tick.select("line"), + text = tick.select("text"); + + path = path.merge(path.enter().insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "#000")); + + tick = tick.merge(tickEnter); + + line = line.merge(tickEnter.append("line") + .attr("stroke", "#000") + .attr(x + "2", k * tickSizeInner)); + + text = text.merge(tickEnter.append("text") + .attr("fill", "#000") + .attr(x, k * spacing) + .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); + + if (context !== selection) { + path = path.transition(context); + tick = tick.transition(context); + line = line.transition(context); + text = text.transition(context); + + tickExit = tickExit.transition(context) + .attr("opacity", epsilon) + .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); }); + + tickEnter + .attr("opacity", epsilon) + .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); }); + } + + tickExit.remove(); + + path + .attr("d", orient === left || orient == right + ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter + : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); + + tick + .attr("opacity", 1) + .attr("transform", function(d) { return transform(position(d)); }); + + line + .attr(x + "2", k * tickSizeInner); + + text + .attr(x, k * spacing) + .text(format); + + selection.filter(entering) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); + + selection + .each(function() { this.__axis = position; }); + } + + axis.scale = function(_) { + return arguments.length ? (scale = _, axis) : scale; + }; + + axis.ticks = function() { + return tickArguments = slice$1.call(arguments), axis; + }; + + axis.tickArguments = function(_) { + return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice(); + }; + + axis.tickValues = function(_) { + return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice(); + }; + + axis.tickFormat = function(_) { + return arguments.length ? (tickFormat = _, axis) : tickFormat; + }; + + axis.tickSize = function(_) { + return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; + }; + + axis.tickSizeInner = function(_) { + return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; + }; + + axis.tickSizeOuter = function(_) { + return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; + }; + + axis.tickPadding = function(_) { + return arguments.length ? (tickPadding = +_, axis) : tickPadding; + }; + + return axis; +} + +function axisTop(scale) { + return axis(top, scale); +} + +function axisRight(scale) { + return axis(right, scale); +} + +function axisBottom(scale) { + return axis(bottom, scale); +} + +function axisLeft(scale) { + return axis(left, scale); +} + +var noop = {value: function() {}}; + +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); +} + +function Dispatch(_) { + this._ = _; +} + +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} + +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } +}; + +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } +} + +function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} + +var xhtml = "http://www.w3.org/1999/xhtml"; + +var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}; + +var namespace = function(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; +}; + +function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; +} + +function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; +} + +var creator = function(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); +}; + +var nextId = 0; + +function local$1() { + return new Local; +} + +function Local() { + this._ = "@" + (++nextId).toString(36); +} + +Local.prototype = local$1.prototype = { + constructor: Local, + get: function(node) { + var id = this._; + while (!(id in node)) if (!(node = node.parentNode)) return; + return node[id]; + }, + set: function(node, value) { + return node[this._] = value; + }, + remove: function(node) { + return this._ in node && delete node[this._]; + }, + toString: function() { + return this._; + } +}; + +var matcher = function(selector) { + return function() { + return this.matches(selector); + }; +}; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!element.matches) { + var vendorMatches = element.webkitMatchesSelector + || element.msMatchesSelector + || element.mozMatchesSelector + || element.oMatchesSelector; + matcher = function(selector) { + return function() { + return vendorMatches.call(this, selector); + }; + }; + } +} + +var matcher$1 = matcher; + +var filterEvents = {}; + +exports.event = null; + +if (typeof document !== "undefined") { + var element$1 = document.documentElement; + if (!("onmouseenter" in element$1)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } +} + +function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function(event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; +} + +function contextListener(listener, index, group) { + return function(event1) { + var event0 = exports.event; // Events can be reentrant (e.g., focus). + exports.event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + exports.event = event0; + } + }; +} + +function parseTypenames$1(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); +} + +function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; +} + +function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function(d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) this.__on = [o]; + else on.push(o); + }; +} + +var selection_on = function(typename, value, capture) { + var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + if (capture == null) capture = false; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); + return this; +}; + +function customEvent(event1, listener, that, args) { + var event0 = exports.event; + event1.sourceEvent = exports.event; + exports.event = event1; + try { + return listener.apply(that, args); + } finally { + exports.event = event0; + } +} + +var sourceEvent = function() { + var current = exports.event, source; + while (source = current.sourceEvent) current = source; + return current; +}; + +var point = function(node, event) { + var svg = node.ownerSVGElement || node; + + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; +}; + +var mouse = function(node) { + var event = sourceEvent(); + if (event.changedTouches) event = event.changedTouches[0]; + return point(node, event); +}; + +function none() {} + +var selector = function(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; +}; + +var selection_select = function(select) { + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + + return new Selection(subgroups, this._parents); +}; + +function empty$1() { + return []; +} + +var selectorAll = function(selector) { + return selector == null ? empty$1 : function() { + return this.querySelectorAll(selector); + }; +}; + +var selection_selectAll = function(select) { + if (typeof select !== "function") select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + + return new Selection(subgroups, parents); +}; + +var selection_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Selection(subgroups, this._parents); +}; + +var sparse = function(update) { + return new Array(update.length); +}; + +var selection_enter = function() { + return new Selection(this._enter || this._groups.map(sparse), this._parents); +}; + +function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; +} + +EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } +}; + +var constant$1 = function(x) { + return function() { + return x; + }; +}; + +var keyPrefix = "$"; // Protect against keys like “__proto__”. + +function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } +} + +function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = {}, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; + + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); + if (keyValue in nodeByKeyValue) { + exit[i] = node; + } else { + nodeByKeyValue[keyValue] = node; + } + } + } + + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = keyPrefix + key.call(parent, data[i], i, data); + if (node = nodeByKeyValue[keyValue]) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue[keyValue] = null; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { + exit[i] = node; + } + } +} + +var selection_data = function(value, key) { + if (!value) { + data = new Array(this.size()), j = -1; + this.each(function(d) { data[++j] = d; }); + return data; + } + + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; + + if (typeof value !== "function") value = constant$1(value); + + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = value.call(parent, parent && parent.__data__, j, parents), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); + + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength); + previous._next = next || null; + } + } + } + + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; +}; + +var selection_exit = function() { + return new Selection(this._exit || this._groups.map(sparse), this._parents); +}; + +var selection_merge = function(selection) { + + for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection(merges, this._parents); +}; + +var selection_order = function() { + + for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + + return this; +}; + +var selection_sort = function(compare) { + if (!compare) compare = ascending$1; + + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } + + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + + return new Selection(sortgroups, this._parents).order(); +}; + +function ascending$1(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} + +var selection_call = function() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; +}; + +var selection_nodes = function() { + var nodes = new Array(this.size()), i = -1; + this.each(function() { nodes[++i] = this; }); + return nodes; +}; + +var selection_node = function() { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) return node; + } + } + + return null; +}; + +var selection_size = function() { + var size = 0; + this.each(function() { ++size; }); + return size; +}; + +var selection_empty = function() { + return !this.node(); +}; + +var selection_each = function(callback) { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) callback.call(node, node.__data__, i, group); + } + } + + return this; +}; + +function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; +} + +function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; +} + +function attrFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttribute(name); + else this.setAttribute(name, v); + }; +} + +function attrFunctionNS(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttributeNS(fullname.space, fullname.local); + else this.setAttributeNS(fullname.space, fullname.local, v); + }; +} + +var selection_attr = function(name, value) { + var fullname = namespace(name); + + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); + } + + return this.each((value == null + ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction) + : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); +}; + +var defaultView = function(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document +}; + +function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; +} + +function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; +} + +var selection_style = function(name, value, priority) { + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : styleValue(this.node(), name); +}; + +function styleValue(node, name) { + return node.style.getPropertyValue(name) + || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); +} + +function propertyRemove(name) { + return function() { + delete this[name]; + }; +} + +function propertyConstant(name, value) { + return function() { + this[name] = value; + }; +} + +function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) delete this[name]; + else this[name] = v; + }; +} + +var selection_property = function(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; +}; + +function classArray(string) { + return string.trim().split(/^|\s+/); +} + +function classList(node) { + return node.classList || new ClassList(node); +} + +function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); +} + +ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } +}; + +function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.add(names[i]); +} + +function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.remove(names[i]); +} + +function classedTrue(names) { + return function() { + classedAdd(this, names); + }; +} + +function classedFalse(names) { + return function() { + classedRemove(this, names); + }; +} + +function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; +} + +var selection_classed = function(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) if (!list.contains(names[i])) return false; + return true; + } + + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); +}; + +function textRemove() { + this.textContent = ""; +} + +function textConstant(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; +} + +var selection_text = function(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction + : textConstant)(value)) + : this.node().textContent; +}; + +function htmlRemove() { + this.innerHTML = ""; +} + +function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; +} + +function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; +} + +var selection_html = function(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; +}; + +function raise() { + if (this.nextSibling) this.parentNode.appendChild(this); +} + +var selection_raise = function() { + return this.each(raise); +}; + +function lower() { + if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); +} + +var selection_lower = function() { + return this.each(lower); +}; + +var selection_append = function(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function() { + return this.appendChild(create.apply(this, arguments)); + }); +}; + +function constantNull() { + return null; +} + +var selection_insert = function(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function() { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); +}; + +function remove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); +} + +var selection_remove = function() { + return this.each(remove); +}; + +var selection_datum = function(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; +}; + +function dispatchEvent(node, type, params) { + var window = defaultView(node), + event = window.CustomEvent; + + if (typeof event === "function") { + event = new event(type, params); + } else { + event = window.document.createEvent("Event"); + if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else event.initEvent(type, false, false); + } + + node.dispatchEvent(event); +} + +function dispatchConstant(type, params) { + return function() { + return dispatchEvent(this, type, params); + }; +} + +function dispatchFunction(type, params) { + return function() { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; +} + +var selection_dispatch = function(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); +}; + +var root = [null]; + +function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; +} + +function selection() { + return new Selection([[document.documentElement]], root); +} + +Selection.prototype = selection.prototype = { + constructor: Selection, + select: selection_select, + selectAll: selection_selectAll, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + merge: selection_merge, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch +}; + +var select = function(selector) { + return typeof selector === "string" + ? new Selection([[document.querySelector(selector)]], [document.documentElement]) + : new Selection([[selector]], root); +}; + +var selectAll = function(selector) { + return typeof selector === "string" + ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) + : new Selection([selector == null ? [] : selector], root); +}; + +var touch = function(node, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; + + for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return point(node, touch); + } + } + + return null; +}; + +var touches = function(node, touches) { + if (touches == null) touches = sourceEvent().touches; + + for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { + points[i] = point(node, touches[i]); + } + + return points; +}; + +function nopropagation() { + exports.event.stopImmediatePropagation(); +} + +var noevent = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +var dragDisable = function(view) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", noevent, true); + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", noevent, true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } +}; + +function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection$$1 = select(view).on("dragstart.drag", null); + if (noclick) { + selection$$1.on("click.drag", noevent, true); + setTimeout(function() { selection$$1.on("click.drag", null); }, 0); + } + if ("onselectstart" in root) { + selection$$1.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } +} + +var constant$2 = function(x) { + return function() { + return x; + }; +}; + +function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { + this.target = target; + this.type = type; + this.subject = subject; + this.identifier = id; + this.active = active; + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + this._ = dispatch; +} + +DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter$1() { + return !exports.event.button; +} + +function defaultContainer() { + return this.parentNode; +} + +function defaultSubject(d) { + return d == null ? {x: exports.event.x, y: exports.event.y} : d; +} + +var drag = function() { + var filter = defaultFilter$1, + container = defaultContainer, + subject = defaultSubject, + gestures = {}, + listeners = dispatch("start", "drag", "end"), + active = 0, + mousedownx, + mousedowny, + mousemoving, + touchending, + clickDistance2 = 0; + + function drag(selection$$1) { + selection$$1 + .on("mousedown.drag", mousedowned) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved) + .on("touchend.drag touchcancel.drag", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); + if (!gesture) return; + select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); + dragDisable(exports.event.view); + nopropagation(); + mousemoving = false; + mousedownx = exports.event.clientX; + mousedowny = exports.event.clientY; + gesture("start"); + } + + function mousemoved() { + noevent(); + if (!mousemoving) { + var dx = exports.event.clientX - mousedownx, dy = exports.event.clientY - mousedowny; + mousemoving = dx * dx + dy * dy > clickDistance2; + } + gestures.mouse("drag"); + } + + function mouseupped() { + select(exports.event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(exports.event.view, mousemoving); + noevent(); + gestures.mouse("end"); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var touches$$1 = exports.event.changedTouches, + c = container.apply(this, arguments), + n = touches$$1.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) { + nopropagation(); + gesture("start"); + } + } + } + + function touchmoved() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + noevent(); + gesture("drag"); + } + } + } + + function touchended() { + var touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, gesture; + + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches$$1[i].identifier]) { + nopropagation(); + gesture("end"); + } + } + } + + function beforestart(id, container, point, that, args) { + var p = point(container, id), s, dx, dy, + sublisteners = listeners.copy(); + + if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { + if ((exports.event.subject = s = subject.apply(that, args)) == null) return false; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return true; + })) return; + + return function gesture(type) { + var p0 = p, n; + switch (type) { + case "start": gestures[id] = gesture, n = active++; break; + case "end": delete gestures[id], --active; // nobreak + case "drag": p = point(container, id), n = active; break; + } + customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); + }; + } + + drag.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter; + }; + + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container; + }; + + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject; + }; + + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + + drag.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); + }; + + return drag; +}; + +var define = function(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; +}; + +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; +} + +function Color() {} + +var darker = 0.7; +var brighter = 1 / darker; + +var reI = "\\s*([+-]?\\d+)\\s*"; +var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; +var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; +var reHex3 = /^#([0-9a-f]{3})$/; +var reHex6 = /^#([0-9a-f]{6})$/; +var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); +var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); +var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); +var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); +var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); +var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); + +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 +}; + +define(Color, color, { + displayable: function() { + return this.rgb().displayable(); + }, + toString: function() { + return this.rgb() + ""; + } +}); + +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} + +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} + +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} + +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} + +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +} + +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; +} + +define(Rgb, rgb, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function() { + return this; + }, + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); + }, + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } +})); + +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} + +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); +} + +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} + +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Hsl, hsl, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); + +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} + +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; + +var Kn = 18; +var Xn = 0.950470; +var Yn = 1; +var Zn = 1.088830; +var t0 = 4 / 29; +var t1 = 6 / 29; +var t2 = 3 * t1 * t1; +var t3 = t1 * t1 * t1; + +function labConvert(o) { + if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) { + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); + } + if (!(o instanceof Rgb)) o = rgbConvert(o); + var b = rgb2xyz(o.r), + a = rgb2xyz(o.g), + l = rgb2xyz(o.b), + x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), + y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), + z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +} + +function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +} + +function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; +} + +define(Lab, lab, extend(Color, { + brighter: function(k) { + return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + darker: function(k) { + return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + rgb: function() { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + y = Yn * lab2xyz(y); + x = Xn * lab2xyz(x); + z = Zn * lab2xyz(z); + return new Rgb( + xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB + xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), + xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), + this.opacity + ); + } +})); + +function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; +} + +function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); +} + +function xyz2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); +} + +function rgb2xyz(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); +} + +function hclConvert(o) { + if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) o = labConvert(o); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); +} + +function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; +} + +define(Hcl, hcl, extend(Color, { + brighter: function(k) { + return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); + }, + darker: function(k) { + return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); + }, + rgb: function() { + return labConvert(this).rgb(); + } +})); + +var A = -0.14861; +var B = +1.78277; +var C = -0.29227; +var D = -0.90649; +var E = +1.97294; +var ED = E * D; +var EB = E * B; +var BC_DA = B * C - D * A; + +function cubehelixConvert(o) { + if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); +} + +function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); +} + +function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Cubehelix, cubehelix, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); + } +})); + +function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; +} + +var basis$1 = function(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var basisClosed = function(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var constant$3 = function(x) { + return function() { + return x; + }; +}; + +function linear(a, d) { + return function(t) { + return a + t * d; + }; +} + +function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; +} + +function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); +} + +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a); + }; +} + +function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant$3(isNaN(a) ? b : a); +} + +var interpolateRgb = ((function rgbGamma(y) { + var color$$1 = gamma(y); + + function rgb$$1(start, end) { + var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), + g = color$$1(start.g, end.g), + b = color$$1(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb$$1.gamma = rgbGamma; + + return rgb$$1; +}))(1); + +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color$$1; + for (i = 0; i < n; ++i) { + color$$1 = rgb(colors[i]); + r[i] = color$$1.r || 0; + g[i] = color$$1.g || 0; + b[i] = color$$1.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color$$1.opacity = 1; + return function(t) { + color$$1.r = r(t); + color$$1.g = g(t); + color$$1.b = b(t); + return color$$1 + ""; + }; + }; +} + +var rgbBasis = rgbSpline(basis$1); +var rgbBasisClosed = rgbSpline(basisClosed); + +var array$1 = function(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(nb), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; +}; + +var date = function(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; +}; + +var reinterpolate = function(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +}; + +var object = function(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; + + for (k in b) { + if (k in a) { + i[k] = interpolateValue(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; +}; + +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; +var reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; +} + +function one(b) { + return function(t) { + return b(t) + ""; + }; +} + +var interpolateString = function(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: reinterpolate(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); +}; + +var interpolateValue = function(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant$3(b) + : (t === "number" ? reinterpolate + : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) + : b instanceof color ? interpolateRgb + : b instanceof Date ? date + : Array.isArray(b) ? array$1 + : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object + : reinterpolate)(a, b); +}; + +var interpolateRound = function(a, b) { + return a = +a, b -= a, function(t) { + return Math.round(a + b * t); + }; +}; + +var degrees = 180 / Math.PI; + +var identity$2 = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 +}; + +var decompose = function(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; +}; + +var cssNode; +var cssRoot; +var cssView; +var svgNode; + +function parseCss(value) { + if (value === "none") return identity$2; + if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +} + +function parseSvg(value) { + if (value == null) return identity$2; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); +} + +function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; +} + +var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); +var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + +var rho = Math.SQRT2; +var rho2 = 2; +var rho4 = 4; +var epsilon2 = 1e-12; + +function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; +} + +function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; +} + +function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); +} + +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] +var interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], + ux1 = p1[0], uy1 = p1[1], w1 = p1[2], + dx = ux1 - ux0, + dy = uy1 - uy0, + d2 = dx * dx + dy * dy, + i, + S; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; +}; + +function hsl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hsl$2 = hsl$1(hue); +var hslLong = hsl$1(nogamma); + +function lab$1(start, end) { + var l = nogamma((start = lab(start)).l, (end = lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; +} + +function hcl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hcl$2 = hcl$1(hue); +var hclLong = hcl$1(nogamma); + +function cubehelix$1(hue$$1) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix$$1(start, end) { + var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix$$1.gamma = cubehelixGamma; + + return cubehelix$$1; + })(1); +} + +var cubehelix$2 = cubehelix$1(hue); +var cubehelixLong = cubehelix$1(nogamma); + +var quantize = function(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); + return samples; +}; + +var frame = 0; +var timeout = 0; +var interval = 0; +var pokeDelay = 1000; +var taskHead; +var taskTail; +var clockLast = 0; +var clockNow = 0; +var clockSkew = 0; +var clock = typeof performance === "object" && performance.now ? performance : Date; +var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); +} + +function clearNow() { + clockNow = 0; +} + +function Timer() { + this._call = + this._time = + this._next = null; +} + +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } +}; + +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; +} + +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } +} + +function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; +} + +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); +} + +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, delay); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clockNow, interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } +} + +var timeout$1 = function(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function(elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; +}; + +var interval$1 = function(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; +}; + +var emptyOn = dispatch("start", "end", "interrupt"); +var emptyTween = []; + +var CREATED = 0; +var SCHEDULED = 1; +var STARTING = 2; +var STARTED = 3; +var RUNNING = 4; +var ENDING = 5; +var ENDED = 6; + +var schedule = function(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); +}; + +function init(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); + return schedule; +} + +function set$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); + return schedule; +} + +function get$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); + return schedule; +} + +function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return timeout$1(start); + + // Interrupt the active transition, if any. + // Dispatch the interrupt event. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. No interrupt event is dispatched + // because the cancelled transitions never started. Note that this also + // removes this transition from the pending list! + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + timeout$1(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(null, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } +} + +var interrupt = function(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) delete node.__transition; +}; + +var selection_interrupt = function(name) { + return this.each(function() { + interrupt(this, name); + }); +}; + +function tweenRemove(id, name) { + var tween0, tween1; + return function() { + var schedule = set$1(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; +} + +function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = set$1(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); + } + + schedule.tween = tween1; + }; +} + +var transition_tween = function(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = get$1(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); +}; + +function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function() { + var schedule = set$1(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function(node) { + return get$1(node, id).value[name]; + }; +} + +var interpolate$$1 = function(a, b) { + var c; + return (typeof b === "number" ? reinterpolate + : b instanceof color ? interpolateRgb + : (c = color(b)) ? (b = c, interpolateRgb) + : interpolateString)(a, b); +}; + +function attrRemove$1(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS$1(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant$1(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrConstantNS$1(fullname, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrFunction$1(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttribute(name); + value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +function attrFunctionNS$1(fullname, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); + value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +var transition_attr = function(name, value) { + var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$$1; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) + : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + "")); +}; + +function attrTweenNS(fullname, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttributeNS(fullname.space, fullname.local, i(t)); + }; + } + tween._value = value; + return tween; +} + +function attrTween(name, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttribute(name, i(t)); + }; + } + tween._value = value; + return tween; +} + +var transition_attrTween = function(name, value) { + var key = "attr." + name; + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + var fullname = namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); +}; + +function delayFunction(id, value) { + return function() { + init(this, id).delay = +value.apply(this, arguments); + }; +} + +function delayConstant(id, value) { + return value = +value, function() { + init(this, id).delay = value; + }; +} + +var transition_delay = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get$1(this.node(), id).delay; +}; + +function durationFunction(id, value) { + return function() { + set$1(this, id).duration = +value.apply(this, arguments); + }; +} + +function durationConstant(id, value) { + return value = +value, function() { + set$1(this, id).duration = value; + }; +} + +var transition_duration = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get$1(this.node(), id).duration; +}; + +function easeConstant(id, value) { + if (typeof value !== "function") throw new Error; + return function() { + set$1(this, id).ease = value; + }; +} + +var transition_ease = function(value) { + var id = this._id; + + return arguments.length + ? this.each(easeConstant(id, value)) + : get$1(this.node(), id).ease; +}; + +var transition_filter = function(match) { + if (typeof match !== "function") match = matcher$1(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Transition(subgroups, this._parents, this._name, this._id); +}; + +var transition_merge = function(transition) { + if (transition._id !== this._id) throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Transition(merges, this._parents, this._name, this._id); +}; + +function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) t = t.slice(0, i); + return !t || t === "start"; + }); +} + +function onFunction(id, name, listener) { + var on0, on1, sit = start(name) ? init : set$1; + return function() { + var schedule = sit(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); + + schedule.on = on1; + }; +} + +var transition_on = function(name, listener) { + var id = this._id; + + return arguments.length < 2 + ? get$1(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); +}; + +function removeFunction(id) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) if (+i !== id) return; + if (parent) parent.removeChild(this); + }; +} + +var transition_remove = function() { + return this.on("end.remove", removeFunction(this._id)); +}; + +var transition_select = function(select$$1) { + var name = this._name, + id = this._id; + + if (typeof select$$1 !== "function") select$$1 = selector(select$$1); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); + } + } + } + + return new Transition(subgroups, this._parents, name, id); +}; + +var transition_selectAll = function(select$$1) { + var name = this._name, + id = this._id; + + if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select$$1.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } + } + + return new Transition(subgroups, parents, name, id); +}; + +var Selection$1 = selection.prototype.constructor; + +var transition_selection = function() { + return new Selection$1(this._groups, this._parents); +}; + +function styleRemove$1(name, interpolate$$2) { + var value00, + value10, + interpolate0; + return function() { + var value0 = styleValue(this, name), + value1 = (this.style.removeProperty(name), styleValue(this, name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value10 = value1); + }; +} + +function styleRemoveEnd(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant$1(name, interpolate$$2, value1) { + var value00, + interpolate0; + return function() { + var value0 = styleValue(this, name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value1); + }; +} + +function styleFunction$1(name, interpolate$$2, value) { + var value00, + value10, + interpolate0; + return function() { + var value0 = styleValue(this, name), + value1 = value(this); + if (value1 == null) value1 = (this.style.removeProperty(name), styleValue(this, name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$2(value00 = value0, value10 = value1); + }; +} + +var transition_style = function(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$$1; + return value == null ? this + .styleTween(name, styleRemove$1(name, i)) + .on("end.style." + name, styleRemoveEnd(name)) + : this.styleTween(name, typeof value === "function" + ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) + : styleConstant$1(name, i, value + ""), priority); +}; + +function styleTween(name, value, priority) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.style.setProperty(name, i(t), priority); + }; + } + tween._value = value; + return tween; +} + +var transition_styleTween = function(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); +}; + +function textConstant$1(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction$1(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; +} + +var transition_text = function(value) { + return this.tween("text", typeof value === "function" + ? textFunction$1(tweenValue(this, "text", value)) + : textConstant$1(value == null ? "" : value + "")); +}; + +var transition_transition = function() { + var name = this._name, + id0 = this._id, + id1 = newId(); + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get$1(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } + } + } + + return new Transition(groups, this._parents, name, id1); +}; + +var id = 0; + +function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; +} + +function transition(name) { + return selection().transition(name); +} + +function newId() { + return ++id; +} + +var selection_prototype = selection.prototype; + +Transition.prototype = transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease +}; + +function linear$1(t) { + return +t; +} + +function quadIn(t) { + return t * t; +} + +function quadOut(t) { + return t * (2 - t); +} + +function quadInOut(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; +} + +function cubicIn(t) { + return t * t * t; +} + +function cubicOut(t) { + return --t * t * t + 1; +} + +function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; +} + +var exponent = 3; + +var polyIn = (function custom(e) { + e = +e; + + function polyIn(t) { + return Math.pow(t, e); + } + + polyIn.exponent = custom; + + return polyIn; +})(exponent); + +var polyOut = (function custom(e) { + e = +e; + + function polyOut(t) { + return 1 - Math.pow(1 - t, e); + } + + polyOut.exponent = custom; + + return polyOut; +})(exponent); + +var polyInOut = (function custom(e) { + e = +e; + + function polyInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; + } + + polyInOut.exponent = custom; + + return polyInOut; +})(exponent); + +var pi = Math.PI; +var halfPi = pi / 2; + +function sinIn(t) { + return 1 - Math.cos(t * halfPi); +} + +function sinOut(t) { + return Math.sin(t * halfPi); +} + +function sinInOut(t) { + return (1 - Math.cos(pi * t)) / 2; +} + +function expIn(t) { + return Math.pow(2, 10 * t - 10); +} + +function expOut(t) { + return 1 - Math.pow(2, -10 * t); +} + +function expInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; +} + +function circleIn(t) { + return 1 - Math.sqrt(1 - t * t); +} + +function circleOut(t) { + return Math.sqrt(1 - --t * t); +} + +function circleInOut(t) { + return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; +} + +var b1 = 4 / 11; +var b2 = 6 / 11; +var b3 = 8 / 11; +var b4 = 3 / 4; +var b5 = 9 / 11; +var b6 = 10 / 11; +var b7 = 15 / 16; +var b8 = 21 / 22; +var b9 = 63 / 64; +var b0 = 1 / b1 / b1; + +function bounceIn(t) { + return 1 - bounceOut(1 - t); +} + +function bounceOut(t) { + return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; +} + +function bounceInOut(t) { + return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; +} + +var overshoot = 1.70158; + +var backIn = (function custom(s) { + s = +s; + + function backIn(t) { + return t * t * ((s + 1) * t - s); + } + + backIn.overshoot = custom; + + return backIn; +})(overshoot); + +var backOut = (function custom(s) { + s = +s; + + function backOut(t) { + return --t * t * ((s + 1) * t + s) + 1; + } + + backOut.overshoot = custom; + + return backOut; +})(overshoot); + +var backInOut = (function custom(s) { + s = +s; + + function backInOut(t) { + return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + } + + backInOut.overshoot = custom; + + return backInOut; +})(overshoot); + +var tau = 2 * Math.PI; +var amplitude = 1; +var period = 0.3; + +var elasticIn = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticIn(t) { + return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); + } + + elasticIn.amplitude = function(a) { return custom(a, p * tau); }; + elasticIn.period = function(p) { return custom(a, p); }; + + return elasticIn; +})(amplitude, period); + +var elasticOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticOut(t) { + return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); + } + + elasticOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticOut.period = function(p) { return custom(a, p); }; + + return elasticOut; +})(amplitude, period); + +var elasticInOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticInOut(t) { + return ((t = t * 2 - 1) < 0 + ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) + : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; + } + + elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticInOut.period = function(p) { return custom(a, p); }; + + return elasticInOut; +})(amplitude, period); + +var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: cubicInOut +}; + +function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + return defaultTiming.time = now(), defaultTiming; + } + } + return timing; +} + +var selection_transition = function(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; + } else { + id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } + } + + return new Transition(groups, this._parents, name, id); +}; + +selection.prototype.interrupt = selection_interrupt; +selection.prototype.transition = selection_transition; + +var root$1 = [null]; + +var active = function(node, name) { + var schedules = node.__transition, + schedule, + i; + + if (schedules) { + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { + return new Transition([[node]], root$1, name, +i); + } + } + } + + return null; +}; + +var constant$4 = function(x) { + return function() { + return x; + }; +}; + +var BrushEvent = function(target, type, selection) { + this.target = target; + this.type = type; + this.selection = selection; +}; + +function nopropagation$1() { + exports.event.stopImmediatePropagation(); +} + +var noevent$1 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +var MODE_DRAG = {name: "drag"}; +var MODE_SPACE = {name: "space"}; +var MODE_HANDLE = {name: "handle"}; +var MODE_CENTER = {name: "center"}; + +var X = { + name: "x", + handles: ["e", "w"].map(type), + input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, + output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } +}; + +var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, + output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } +}; + +var XY = { + name: "xy", + handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type), + input: function(xy) { return xy; }, + output: function(xy) { return xy; } +}; + +var cursors = { + overlay: "crosshair", + selection: "move", + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" +}; + +var flipX = { + e: "w", + w: "e", + nw: "ne", + ne: "nw", + se: "sw", + sw: "se" +}; + +var flipY = { + n: "s", + s: "n", + nw: "sw", + ne: "se", + se: "ne", + sw: "nw" +}; + +var signsX = { + overlay: +1, + selection: +1, + n: null, + e: +1, + s: null, + w: -1, + nw: -1, + ne: +1, + se: +1, + sw: -1 +}; + +var signsY = { + overlay: +1, + selection: +1, + n: -1, + e: null, + s: +1, + w: null, + nw: -1, + ne: -1, + se: +1, + sw: +1 +}; + +function type(t) { + return {type: t}; +} + +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !exports.event.button; +} + +function defaultExtent() { + var svg = this.ownerSVGElement || this; + return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; +} + +// Like d3.local, but with the name “__brush” rather than auto-generated. +function local$$1(node) { + while (!node.__brush) if (!(node = node.parentNode)) return; + return node.__brush; +} + +function empty(extent) { + return extent[0][0] === extent[1][0] + || extent[0][1] === extent[1][1]; +} + +function brushSelection(node) { + var state = node.__brush; + return state ? state.dim.output(state.selection) : null; +} + +function brushX() { + return brush$1(X); +} + +function brushY() { + return brush$1(Y); +} + +var brush = function() { + return brush$1(XY); +}; + +function brush$1(dim) { + var extent = defaultExtent, + filter = defaultFilter, + listeners = dispatch(brush, "start", "brush", "end"), + handleSize = 6, + touchending; + + function brush(group) { + var overlay = group + .property("__brush", initialize) + .selectAll(".overlay") + .data([type("overlay")]); + + overlay.enter().append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", cursors.overlay) + .merge(overlay) + .each(function() { + var extent = local$$1(this).extent; + select(this) + .attr("x", extent[0][0]) + .attr("y", extent[0][1]) + .attr("width", extent[1][0] - extent[0][0]) + .attr("height", extent[1][1] - extent[0][1]); + }); + + group.selectAll(".selection") + .data([type("selection")]) + .enter().append("rect") + .attr("class", "selection") + .attr("cursor", cursors.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges"); + + var handle = group.selectAll(".handle") + .data(dim.handles, function(d) { return d.type; }); + + handle.exit().remove(); + + handle.enter().append("rect") + .attr("class", function(d) { return "handle handle--" + d.type; }) + .attr("cursor", function(d) { return cursors[d.type]; }); + + group + .each(redraw) + .attr("fill", "none") + .attr("pointer-events", "all") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .on("mousedown.brush touchstart.brush", started); + } + + brush.move = function(group, selection$$1) { + if (group.selection) { + group + .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) + .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) + .tween("brush", function() { + var that = this, + state = that.__brush, + emit = emitter(that, arguments), + selection0 = state.selection, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent), + i = interpolateValue(selection0, selection1); + + function tween(t) { + state.selection = t === 1 && empty(selection1) ? null : i(t); + redraw.call(that); + emit.brush(); + } + + return selection0 && selection1 ? tween : tween(1); + }); + } else { + group + .each(function() { + var that = this, + args = arguments, + state = that.__brush, + selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent), + emit = emitter(that, args).beforestart(); + + interrupt(that); + state.selection = selection1 == null || empty(selection1) ? null : selection1; + redraw.call(that); + emit.start().brush().end(); + }); + } + }; + + function redraw() { + var group = select(this), + selection$$1 = local$$1(this).selection; + + if (selection$$1) { + group.selectAll(".selection") + .style("display", null) + .attr("x", selection$$1[0][0]) + .attr("y", selection$$1[0][1]) + .attr("width", selection$$1[1][0] - selection$$1[0][0]) + .attr("height", selection$$1[1][1] - selection$$1[0][1]); + + group.selectAll(".handle") + .style("display", null) + .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; }) + .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; }) + .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; }) + .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; }); + } + + else { + group.selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + } + + function emitter(that, args) { + return that.__brush.emitter || new Emitter(that, args); + } + + function Emitter(that, args) { + this.that = that; + this.args = args; + this.state = that.__brush; + this.active = 0; + } + + Emitter.prototype = { + beforestart: function() { + if (++this.active === 1) this.state.emitter = this, this.starting = true; + return this; + }, + start: function() { + if (this.starting) this.starting = false, this.emit("start"); + return this; + }, + brush: function() { + this.emit("brush"); + return this; + }, + end: function() { + if (--this.active === 0) delete this.state.emitter, this.emit("end"); + return this; + }, + emit: function(type) { + customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function started() { + if (exports.event.touches) { if (exports.event.changedTouches.length < exports.event.touches.length) return noevent$1(); } + else if (touchending) return; + if (!filter.apply(this, arguments)) return; + + var that = this, + type = exports.event.target.__data__.type, + mode = (exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (exports.event.altKey ? MODE_CENTER : MODE_HANDLE), + signX = dim === Y ? null : signsX[type], + signY = dim === X ? null : signsY[type], + state = local$$1(that), + extent = state.extent, + selection$$1 = state.selection, + W = extent[0][0], w0, w1, + N = extent[0][1], n0, n1, + E = extent[1][0], e0, e1, + S = extent[1][1], s0, s1, + dx, + dy, + moving, + shifting = signX && signY && exports.event.shiftKey, + lockX, + lockY, + point0 = mouse(that), + point = point0, + emit = emitter(that, arguments).beforestart(); + + if (type === "overlay") { + state.selection = selection$$1 = [ + [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], + [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] + ]; + } else { + w0 = selection$$1[0][0]; + n0 = selection$$1[0][1]; + e0 = selection$$1[1][0]; + s0 = selection$$1[1][1]; + } + + w1 = w0; + n1 = n0; + e1 = e0; + s1 = s0; + + var group = select(that) + .attr("pointer-events", "none"); + + var overlay = group.selectAll(".overlay") + .attr("cursor", cursors[type]); + + if (exports.event.touches) { + group + .on("touchmove.brush", moved, true) + .on("touchend.brush touchcancel.brush", ended, true); + } else { + var view = select(exports.event.view) + .on("keydown.brush", keydowned, true) + .on("keyup.brush", keyupped, true) + .on("mousemove.brush", moved, true) + .on("mouseup.brush", ended, true); + + dragDisable(exports.event.view); + } + + nopropagation$1(); + interrupt(that); + redraw.call(that); + emit.start(); + + function moved() { + var point1 = mouse(that); + if (shifting && !lockX && !lockY) { + if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; + else lockX = true; + } + point = point1; + moving = true; + noevent$1(); + move(); + } + + function move() { + var t; + + dx = point[0] - point0[0]; + dy = point[1] - point0[1]; + + switch (mode) { + case MODE_SPACE: + case MODE_DRAG: { + if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; + if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; + break; + } + case MODE_HANDLE: { + if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; + else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; + if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; + else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; + break; + } + case MODE_CENTER: { + if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); + if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); + break; + } + } + + if (e1 < w1) { + signX *= -1; + t = w0, w0 = e0, e0 = t; + t = w1, w1 = e1, e1 = t; + if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); + } + + if (s1 < n1) { + signY *= -1; + t = n0, n0 = s0, s0 = t; + t = n1, n1 = s1, s1 = t; + if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); + } + + if (state.selection) selection$$1 = state.selection; // May be set by brush.move! + if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0]; + if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1]; + + if (selection$$1[0][0] !== w1 + || selection$$1[0][1] !== n1 + || selection$$1[1][0] !== e1 + || selection$$1[1][1] !== s1) { + state.selection = [[w1, n1], [e1, s1]]; + redraw.call(that); + emit.brush(); + } + } + + function ended() { + nopropagation$1(); + if (exports.event.touches) { + if (exports.event.touches.length) return; + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + group.on("touchmove.brush touchend.brush touchcancel.brush", null); + } else { + yesdrag(exports.event.view, moving); + view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); + } + group.attr("pointer-events", "all"); + overlay.attr("cursor", cursors.overlay); + if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)! + if (empty(selection$$1)) state.selection = null, redraw.call(that); + emit.end(); + } + + function keydowned() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + shifting = signX && signY; + break; + } + case 18: { // ALT + if (mode === MODE_HANDLE) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + move(); + } + break; + } + case 32: { // SPACE; takes priority over ALT + if (mode === MODE_HANDLE || mode === MODE_CENTER) { + if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; + if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; + mode = MODE_SPACE; + overlay.attr("cursor", cursors.selection); + move(); + } + break; + } + default: return; + } + noevent$1(); + } + + function keyupped() { + switch (exports.event.keyCode) { + case 16: { // SHIFT + if (shifting) { + lockX = lockY = shifting = false; + move(); + } + break; + } + case 18: { // ALT + if (mode === MODE_CENTER) { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + move(); + } + break; + } + case 32: { // SPACE + if (mode === MODE_SPACE) { + if (exports.event.altKey) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + } else { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + } + overlay.attr("cursor", cursors[type]); + move(); + } + break; + } + default: return; + } + noevent$1(); + } + } + + function initialize() { + var state = this.__brush || {selection: null}; + state.extent = extent.apply(this, arguments); + state.dim = dim; + return state; + } + + brush.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; + }; + + brush.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter; + }; + + brush.handleSize = function(_) { + return arguments.length ? (handleSize = +_, brush) : handleSize; + }; + + brush.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? brush : value; + }; + + return brush; +} + +var cos = Math.cos; +var sin = Math.sin; +var pi$1 = Math.PI; +var halfPi$1 = pi$1 / 2; +var tau$1 = pi$1 * 2; +var max$1 = Math.max; + +function compareValue(compare) { + return function(a, b) { + return compare( + a.source.value + a.target.value, + b.source.value + b.target.value + ); + }; +} + +var chord = function() { + var padAngle = 0, + sortGroups = null, + sortSubgroups = null, + sortChords = null; + + function chord(matrix) { + var n = matrix.length, + groupSums = [], + groupIndex = sequence(n), + subgroupIndex = [], + chords = [], + groups = chords.groups = new Array(n), + subgroups = new Array(n * n), + k, + x, + x0, + dx, + i, + j; + + // Compute the sum. + k = 0, i = -1; while (++i < n) { + x = 0, j = -1; while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(sequence(n)); + k += x; + } + + // Sort groups… + if (sortGroups) groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + + // Sort subgroups… + if (sortSubgroups) subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + + // Convert the sum to scaling factor for [0, 2pi]. + // TODO Allow start and end angle to be specified? + // TODO Allow padding to be specified as percentage? + k = max$1(0, tau$1 - padAngle * n) / k; + dx = k ? padAngle : tau$1 / n; + + // Compute the start and end angle for each group and subgroup. + // Note: Opera has a bug reordering object literal properties! + x = 0, i = -1; while (++i < n) { + x0 = x, j = -1; while (++j < n) { + var di = groupIndex[i], + dj = subgroupIndex[di][j], + v = matrix[di][dj], + a0 = x, + a1 = x += v * k; + subgroups[dj * n + di] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += dx; + } + + // Generate chords for each (non-empty) subgroup-subgroup link. + i = -1; while (++i < n) { + j = i - 1; while (++j < n) { + var source = subgroups[j * n + i], + target = subgroups[i * n + j]; + if (source.value || target.value) { + chords.push(source.value < target.value + ? {source: target, target: source} + : {source: source, target: target}); + } + } + } + + return sortChords ? chords.sort(sortChords) : chords; + } + + chord.padAngle = function(_) { + return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; + }; + + chord.sortGroups = function(_) { + return arguments.length ? (sortGroups = _, chord) : sortGroups; + }; + + chord.sortSubgroups = function(_) { + return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; + }; + + chord.sortChords = function(_) { + return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; + }; + + return chord; +}; + +var slice$2 = Array.prototype.slice; + +var constant$5 = function(x) { + return function() { + return x; + }; +}; + +var pi$2 = Math.PI; +var tau$2 = 2 * pi$2; +var epsilon$1 = 1e-6; +var tauEpsilon = tau$2 - epsilon$1; + +function Path() { + this._x0 = this._y0 = // start of current subpath + this._x1 = this._y1 = null; // end of current subpath + this._ = ""; +} + +function path() { + return new Path; +} + +Path.prototype = path.prototype = { + constructor: Path, + moveTo: function(x, y) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); + }, + closePath: function() { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._ += "Z"; + } + }, + lineTo: function(x, y) { + this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); + }, + quadraticCurveTo: function(x1, y1, x, y) { + this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { + this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + arcTo: function(x1, y1, x2, y2, r) { + x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; + var x0 = this._x1, + y0 = this._y1, + x21 = x2 - x1, + y21 = y2 - y1, + x01 = x0 - x1, + y01 = y0 - y1, + l01_2 = x01 * x01 + y01 * y01; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x1,y1). + if (this._x1 === null) { + this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. + else if (!(l01_2 > epsilon$1)) {} + + // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? + // Equivalently, is (x1,y1) coincident with (x2,y2)? + // Or, is the radius zero? Line to (x1,y1). + else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) { + this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Otherwise, draw an arc! + else { + var x20 = x2 - x0, + y20 = y2 - y0, + l21_2 = x21 * x21 + y21 * y21, + l20_2 = x20 * x20 + y20 * y20, + l21 = Math.sqrt(l21_2), + l01 = Math.sqrt(l01_2), + l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), + t01 = l / l01, + t21 = l / l21; + + // If the start tangent is not coincident with (x0,y0), line to. + if (Math.abs(t01 - 1) > epsilon$1) { + this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); + } + + this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); + } + }, + arc: function(x, y, r, a0, a1, ccw) { + x = +x, y = +y, r = +r; + var dx = r * Math.cos(a0), + dy = r * Math.sin(a0), + x0 = x + dx, + y0 = y + dy, + cw = 1 ^ ccw, + da = ccw ? a0 - a1 : a1 - a0; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x0,y0). + if (this._x1 === null) { + this._ += "M" + x0 + "," + y0; + } + + // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). + else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) { + this._ += "L" + x0 + "," + y0; + } + + // Is this arc empty? We’re done. + if (!r) return; + + // Does the angle go the wrong way? Flip the direction. + if (da < 0) da = da % tau$2 + tau$2; + + // Is this a complete circle? Draw two arcs to complete the circle. + if (da > tauEpsilon) { + this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); + } + + // Is this arc non-empty? Draw an arc! + else if (da > epsilon$1) { + this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); + } + }, + rect: function(x, y, w, h) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; + }, + toString: function() { + return this._; + } +}; + +function defaultSource(d) { + return d.source; +} + +function defaultTarget(d) { + return d.target; +} + +function defaultRadius(d) { + return d.radius; +} + +function defaultStartAngle(d) { + return d.startAngle; +} + +function defaultEndAngle(d) { + return d.endAngle; +} + +var ribbon = function() { + var source = defaultSource, + target = defaultTarget, + radius = defaultRadius, + startAngle = defaultStartAngle, + endAngle = defaultEndAngle, + context = null; + + function ribbon() { + var buffer, + argv = slice$2.call(arguments), + s = source.apply(this, argv), + t = target.apply(this, argv), + sr = +radius.apply(this, (argv[0] = s, argv)), + sa0 = startAngle.apply(this, argv) - halfPi$1, + sa1 = endAngle.apply(this, argv) - halfPi$1, + sx0 = sr * cos(sa0), + sy0 = sr * sin(sa0), + tr = +radius.apply(this, (argv[0] = t, argv)), + ta0 = startAngle.apply(this, argv) - halfPi$1, + ta1 = endAngle.apply(this, argv) - halfPi$1; + + if (!context) context = buffer = path(); + + context.moveTo(sx0, sy0); + context.arc(0, 0, sr, sa0, sa1); + if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? + context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); + context.arc(0, 0, tr, ta0, ta1); + } + context.quadraticCurveTo(0, 0, sx0, sy0); + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + ribbon.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius; + }; + + ribbon.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle; + }; + + ribbon.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle; + }; + + ribbon.source = function(_) { + return arguments.length ? (source = _, ribbon) : source; + }; + + ribbon.target = function(_) { + return arguments.length ? (target = _, ribbon) : target; + }; + + ribbon.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + }; + + return ribbon; +}; + +var prefix = "$"; + +function Map() {} + +Map.prototype = map$1.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); + } +}; + +function map$1(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +var nest = function() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; + + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) return rollup != null + ? rollup(array) : (sortValues != null + ? array.sort(sortValues) + : array); + + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map$1(), + values, + result = createResult(); + + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } + + valuesByKey.each(function(values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); + + return result; + } + + function entries(map, depth) { + if (++depth > keys.length) return map; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) array = map.entries(); + else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); + return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; + } + + return nest = { + object: function(array) { return apply(array, 0, createObject, setObject); }, + map: function(array) { return apply(array, 0, createMap, setMap); }, + entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, + key: function(d) { keys.push(d); return nest; }, + sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, + sortValues: function(order) { sortValues = order; return nest; }, + rollup: function(f) { rollup = f; return nest; } + }; +}; + +function createObject() { + return {}; +} + +function setObject(object, key, value) { + object[key] = value; +} + +function createMap() { + return map$1(); +} + +function setMap(map, key, value) { + map.set(key, value); +} + +function Set() {} + +var proto = map$1.prototype; + +Set.prototype = set$2.prototype = { + constructor: Set, + has: proto.has, + add: function(value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each +}; + +function set$2(object, f) { + var set = new Set; + + // Copy constructor. + if (object instanceof Set) object.each(function(value) { set.add(value); }); + + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) while (++i < n) set.add(object[i]); + else while (++i < n) set.add(f(object[i], i, object)); + } + + return set; +} + +var keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; +}; + +var values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; +}; + +var entries = function(map) { + var entries = []; + for (var key in map) entries.push({key: key, value: map[key]}); + return entries; +}; + +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); +} + +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; +} + +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; +} + +var dsv = function(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), + delimiterCode = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns; + return rows; + } + + function parseRows(text, f) { + var EOL = {}, // sentinel value for end-of-line + EOF = {}, // sentinel value for end-of-file + rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // the current line number + t, // the current token + eol; // is the current token followed by EOL? + + function token() { + if (I >= N) return EOF; // special case: end of file + if (eol) return eol = false, EOL; // special case: end of line + + // special case: quotes + var j = I, c; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; + } + } + I = i + 2; + c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; + } + return text.slice(j + 1, i).replace(/""/g, "\""); + } + + // common case: find next delimiter or newline + while (I < N) { + var k = 1; + c = text.charCodeAt(I++); + if (c === 10) eol = true; // \n + else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n + else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } + + // special case: last token before EOF + return text.slice(j); + } + + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); + } + if (f && (a = f(a, n++)) == null) continue; + rows.push(a); + } + + return rows; + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + })).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(text) { + return text == null ? "" + : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\"" + : text; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatRows: formatRows + }; +}; + +var csv = dsv(","); + +var csvParse = csv.parse; +var csvParseRows = csv.parseRows; +var csvFormat = csv.format; +var csvFormatRows = csv.formatRows; + +var tsv = dsv("\t"); + +var tsvParse = tsv.parse; +var tsvParseRows = tsv.parseRows; +var tsvFormat = tsv.format; +var tsvFormatRows = tsv.formatRows; + +var center$1 = function(x, y) { + var nodes; + + if (x == null) x = 0; + if (y == null) y = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + + force.initialize = function(_) { + nodes = _; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var constant$6 = function(x) { + return function() { + return x; + }; +}; + +var jiggle = function() { + return (Math.random() - 0.5) * 1e-6; +}; + +var tree_add = function(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); +}; + +function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; +} + +function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } + + // If there were no (valid) points, inherit the existing extent. + if (x1 < x0) x0 = this._x0, x1 = this._x1; + if (y1 < y0) y0 = this._y0, y1 = this._y1; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + + return this; +} + +var tree_cover = function(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else if (x0 > x || x > x1 || y0 > y || y > y1) { + var z = x1 - x0, + node = this._root, + parent, + i; + + switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { + case 0: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); + break; + } + case 1: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); + break; + } + case 2: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); + break; + } + case 3: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); + break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + // If the quadtree covers the point already, just return. + else return this; + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; +}; + +var tree_data = function() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; +}; + +var tree_extent = function(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; +}; + +var Quad = function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}; + +var tree_find = function(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; +}; + +var tree_remove = function(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; +}; + +function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; +} + +var tree_root = function() { + return this._root; +}; + +var tree_size = function() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; +}; + +var tree_visit = function(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; +}; + +var tree_visitAfter = function(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; +}; + +function defaultX(d) { + return d[0]; +} + +var tree_x = function(_) { + return arguments.length ? (this._x = _, this) : this._x; +}; + +function defaultY(d) { + return d[1]; +} + +var tree_y = function(_) { + return arguments.length ? (this._y = _, this) : this._y; +}; + +function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); +} + +function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; +} + +function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; +} + +var treeProto = quadtree.prototype = Quadtree.prototype; + +treeProto.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy(child); + } + } + } + + return copy; +}; + +treeProto.add = tree_add; +treeProto.addAll = addAll; +treeProto.cover = tree_cover; +treeProto.data = tree_data; +treeProto.extent = tree_extent; +treeProto.find = tree_find; +treeProto.remove = tree_remove; +treeProto.removeAll = removeAll; +treeProto.root = tree_root; +treeProto.size = tree_size; +treeProto.visit = tree_visit; +treeProto.visitAfter = tree_visitAfter; +treeProto.x = tree_x; +treeProto.y = tree_y; + +function x(d) { + return d.x + d.vx; +} + +function y(d) { + return d.y + d.vy; +} + +var collide = function(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; + + if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius); + + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; + + for (var k = 0; k < iterations; ++k) { + tree = quadtree(nodes, x, y).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + + function prepare(quad) { + if (quad.data) return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius; + }; + + return force; +}; + +function index(d) { + return d.index; +} + +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; +} + +var link = function(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant$6(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = map$1(nodes, id), + link; + + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance; + }; + + return force; +}; + +function x$1(d) { + return d.x; +} + +function y$1(d) { + return d.y; +} + +var initialRadius = 10; +var initialAngle = Math.PI * (3 - Math.sqrt(5)); + +var simulation = function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = map$1(), + stepper = timer(step), + event = dispatch("tick", "end"); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick() { + var i, n = nodes.length, node; + + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function(force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) radius = Infinity; + else radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; +}; + +var manyBody = function() { + var nodes, + node, + alpha, + strength = constant$6(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } + + function accumulate(quad) { + var strength = 0, q, c, x$$1, y$$1, i; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x$$1 = y$$1 = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = q.value)) { + strength += c, x$$1 += c * q.x, y$$1 += c * q.y; + } + } + quad.x = x$$1 / strength; + quad.y = y$$1 / strength; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do strength += strengths[q.data.index]; + while (q = q.next); + } + + quad.value = strength; + } + + function apply(quad, x1, _, x2) { + if (!quad.value) return true; + + var x$$1 = quad.x - node.x, + y$$1 = quad.y - node.y, + w = x2 - x1, + l = x$$1 * x$$1 + y$$1 * y$$1; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x$$1 * quad.value * alpha / l; + node.vy += y$$1 * quad.value * alpha / l; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; + if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + } + + do if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x$$1 * w; + node.vy += y$$1 * w; + } while (quad = quad.next); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; + }; + + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; +}; + +var x$2 = function(x) { + var strength = constant$6(0.1), + nodes, + strengths, + xz; + + if (typeof x !== "function") x = constant$6(x == null ? 0 : +x); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; + }; + + force.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x; + }; + + return force; +}; + +var y$2 = function(y) { + var strength = constant$6(0.1), + nodes, + strengths, + yz; + + if (typeof y !== "function") y = constant$6(y == null ? 0 : +y); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; + }; + + force.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y; + }; + + return force; +}; + +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. +var formatDecimal = function(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); + + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; +}; + +var exponent$1 = function(x) { + return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; +}; + +var formatGroup = function(grouping, thousands) { + return function(value, width) { + var i = value.length, + t = [], + j = 0, + g = grouping[0], + length = 0; + + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = grouping[j = (j + 1) % grouping.length]; + } + + return t.reverse().join(thousands); + }; +}; + +var formatNumerals = function(numerals) { + return function(value) { + return value.replace(/[0-9]/g, function(i) { + return numerals[+i]; + }); + }; +}; + +var formatDefault = function(x, p) { + x = x.toPrecision(p); + + out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (x[i]) { + case ".": i0 = i1 = i; break; + case "0": if (i0 === 0) i0 = i; i1 = i; break; + case "e": break out; + default: if (i0 > 0) i0 = 0; break; + } + } + + return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; +}; + +var prefixExponent; + +var formatPrefixAuto = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! +}; + +var formatRounded = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient + : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) + : coefficient + new Array(exponent - coefficient.length + 2).join("0"); +}; + +var formatTypes = { + "": formatDefault, + "%": function(x, p) { return (x * 100).toFixed(p); }, + "b": function(x) { return Math.round(x).toString(2); }, + "c": function(x) { return x + ""; }, + "d": function(x) { return Math.round(x).toString(10); }, + "e": function(x, p) { return x.toExponential(p); }, + "f": function(x, p) { return x.toFixed(p); }, + "g": function(x, p) { return x.toPrecision(p); }, + "o": function(x) { return Math.round(x).toString(8); }, + "p": function(x, p) { return formatRounded(x * 100, p); }, + "r": formatRounded, + "s": formatPrefixAuto, + "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, + "x": function(x) { return Math.round(x).toString(16); } +}; + +// [[fill]align][sign][symbol][0][width][,][.precision][type] +var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; + +function formatSpecifier(specifier) { + return new FormatSpecifier(specifier); +} + +formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof + +function FormatSpecifier(specifier) { + if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); + + var match, + fill = match[1] || " ", + align = match[2] || ">", + sign = match[3] || "-", + symbol = match[4] || "", + zero = !!match[5], + width = match[6] && +match[6], + comma = !!match[7], + precision = match[8] && +match[8].slice(1), + type = match[9] || ""; + + // The "n" type is an alias for ",g". + if (type === "n") comma = true, type = "g"; + + // Map invalid types to the default format. + else if (!formatTypes[type]) type = ""; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + + this.fill = fill; + this.align = align; + this.sign = sign; + this.symbol = symbol; + this.zero = zero; + this.width = width; + this.comma = comma; + this.precision = precision; + this.type = type; +} + +FormatSpecifier.prototype.toString = function() { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width == null ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + + this.type; +}; + +var identity$3 = function(x) { + return x; +}; + +var prefixes = ["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"]; + +var formatLocale = function(locale) { + var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, + currency = locale.currency, + decimal = locale.decimal, + numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3, + percent = locale.percent || "%"; + + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + type = specifier.type; + + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; + + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = formatTypes[type], + maybeSuffix = !type || /[defgprs%]/.test(type); + + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision == null ? (type ? 6 : 12) + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); + + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; + + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + + // Perform the initial formatting. + var valueNegative = value < 0; + value = formatType(Math.abs(value), precision); + + // If a negative value rounds to zero during formatting, treat as positive. + if (valueNegative && +value === 0) valueNegative = false; + + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); + + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) value = group(value, Infinity); + + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; + + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": value = valuePrefix + value + valueSuffix + padding; break; + case "=": value = valuePrefix + padding + value + valueSuffix; break; + case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; + default: value = padding + valuePrefix + value + valueSuffix; break; + } + + return numerals(value); + } + + format.toString = function() { + return specifier + ""; + }; + + return format; + } + + function formatPrefix(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function(value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; +}; + +var locale$1; + + + +defaultLocale({ + decimal: ".", + thousands: ",", + grouping: [3], + currency: ["$", ""] +}); + +function defaultLocale(definition) { + locale$1 = formatLocale(definition); + exports.format = locale$1.format; + exports.formatPrefix = locale$1.formatPrefix; + return locale$1; +} + +var precisionFixed = function(step) { + return Math.max(0, -exponent$1(Math.abs(step))); +}; + +var precisionPrefix = function(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); +}; + +var precisionRound = function(step, max) { + step = Math.abs(step), max = Math.abs(max) - step; + return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; +}; + +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + +var adder = function() { + return new Adder; +}; + +function Adder() { + this.reset(); +} + +Adder.prototype = { + constructor: Adder, + reset: function() { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function(y) { + add$1(temp, y, this.t); + add$1(this, temp.s, this.s); + if (this.s) this.t += temp.t; + else this.s = temp.t; + }, + valueOf: function() { + return this.s; + } +}; + +var temp = new Adder; + +function add$1(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); +} + +var epsilon$2 = 1e-6; +var epsilon2$1 = 1e-12; +var pi$3 = Math.PI; +var halfPi$2 = pi$3 / 2; +var quarterPi = pi$3 / 4; +var tau$3 = pi$3 * 2; + +var degrees$1 = 180 / pi$3; +var radians = pi$3 / 180; + +var abs = Math.abs; +var atan = Math.atan; +var atan2 = Math.atan2; +var cos$1 = Math.cos; +var ceil = Math.ceil; +var exp = Math.exp; + +var log = Math.log; +var pow = Math.pow; +var sin$1 = Math.sin; +var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; +var sqrt = Math.sqrt; +var tan = Math.tan; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x); +} + +function asin(x) { + return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x); +} + +function haversin(x) { + return (x = sin$1(x / 2)) * x; +} + +function noop$1() {} + +function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); + } +} + +var streamObjectType = { + Feature: function(object, stream) { + streamGeometry(object.geometry, stream); + }, + FeatureCollection: function(object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) streamGeometry(features[i].geometry, stream); + } +}; + +var streamGeometryType = { + Sphere: function(object, stream) { + stream.sphere(); + }, + Point: function(object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function(object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamLine(coordinates[i], stream, 0); + }, + Polygon: function(object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function(object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) streamGeometry(geometries[i], stream); + } +}; + +function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); +} + +function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); +} + +var geoStream = function(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); + } +}; + +var areaRingSum = adder(); + +var areaSum = adder(); +var lambda00; +var phi00; +var lambda0; +var cosPhi0; +var sinPhi0; + +var areaStream = { + point: noop$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: function() { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function() { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = noop$1; + }, + sphere: function() { + areaSum.add(tau$3); + } +}; + +function areaRingStart() { + areaStream.point = areaPointFirst; +} + +function areaRingEnd() { + areaPoint(lambda00, phi00); +} + +function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= radians, phi *= radians; + lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); +} + +function areaPoint(lambda, phi) { + lambda *= radians, phi *= radians; + phi = phi / 2 + quarterPi; // half the angular distance from south pole + + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = cos$1(phi), + sinPhi = sin$1(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * cos$1(adLambda), + v = k * sdLambda * sin$1(adLambda); + areaRingSum.add(atan2(v, u)); + + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; +} + +var area = function(object) { + areaSum.reset(); + geoStream(object, areaStream); + return areaSum * 2; +}; + +function spherical(cartesian) { + return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; +} + +function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); + return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; +} + +function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +function cartesianCross(a, b) { + return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; +} + +// TODO return a +function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; +} + +function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; +} + +// TODO return d +function cartesianNormalizeInPlace(d) { + var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; +} + +var lambda0$1; +var phi0; +var lambda1; +var phi1; +var lambda2; +var lambda00$1; +var phi00$1; +var p0; +var deltaSum = adder(); +var ranges; +var range; + +var boundsStream = { + point: boundsPoint, + lineStart: boundsLineStart, + lineEnd: boundsLineEnd, + polygonStart: function() { + boundsStream.point = boundsRingPoint; + boundsStream.lineStart = boundsRingStart; + boundsStream.lineEnd = boundsRingEnd; + deltaSum.reset(); + areaStream.polygonStart(); + }, + polygonEnd: function() { + areaStream.polygonEnd(); + boundsStream.point = boundsPoint; + boundsStream.lineStart = boundsLineStart; + boundsStream.lineEnd = boundsLineEnd; + if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + else if (deltaSum > epsilon$2) phi1 = 90; + else if (deltaSum < -epsilon$2) phi0 = -90; + range[0] = lambda0$1, range[1] = lambda1; + } +}; + +function boundsPoint(lambda, phi) { + ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; +} + +function linePoint(lambda, phi) { + var p = cartesian([lambda * radians, phi * radians]); + if (p0) { + var normal = cartesianCross(p0, p), + equatorial = [normal[1], -normal[0], 0], + inflection = cartesianCross(equatorial, normal); + cartesianNormalizeInPlace(inflection); + inflection = spherical(inflection); + var delta = lambda - lambda2, + sign$$1 = delta > 0 ? 1 : -1, + lambdai = inflection[0] * degrees$1 * sign$$1, + phii, + antimeridian = abs(delta) > 180; + if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = inflection[1] * degrees$1; + if (phii > phi1) phi1 = phii; + } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = -inflection[1] * degrees$1; + if (phii < phi0) phi0 = phii; + } else { + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + } + if (antimeridian) { + if (lambda < lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } else { + if (lambda1 >= lambda0$1) { + if (lambda < lambda0$1) lambda0$1 = lambda; + if (lambda > lambda1) lambda1 = lambda; + } else { + if (lambda > lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } + } + } else { + ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); + } + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + p0 = p, lambda2 = lambda; +} + +function boundsLineStart() { + boundsStream.point = linePoint; +} + +function boundsLineEnd() { + range[0] = lambda0$1, range[1] = lambda1; + boundsStream.point = boundsPoint; + p0 = null; +} + +function boundsRingPoint(lambda, phi) { + if (p0) { + var delta = lambda - lambda2; + deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); + } else { + lambda00$1 = lambda, phi00$1 = phi; + } + areaStream.point(lambda, phi); + linePoint(lambda, phi); +} + +function boundsRingStart() { + areaStream.lineStart(); +} + +function boundsRingEnd() { + boundsRingPoint(lambda00$1, phi00$1); + areaStream.lineEnd(); + if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180); + range[0] = lambda0$1, range[1] = lambda1; + p0 = null; +} + +// Finds the left-right distance between two longitudes. +// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want +// the distance between ±180° to be 360°. +function angle(lambda0, lambda1) { + return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; +} + +function rangeCompare(a, b) { + return a[0] - b[0]; +} + +function rangeContains(range, x) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; +} + +var bounds = function(feature) { + var i, n, a, b, merged, deltaMax, delta; + + phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); + ranges = []; + geoStream(feature, boundsStream); + + // First, sort ranges by their minimum longitudes. + if (n = ranges.length) { + ranges.sort(rangeCompare); + + // Then, merge any ranges that overlap. + for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { + b = ranges[i]; + if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + + // Finally, find the largest gap between the merged ranges. + // The final bounding box will be the inverse of this gap. + for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { + b = merged[i]; + if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + } + } + + ranges = range = null; + + return lambda0$1 === Infinity || phi0 === Infinity + ? [[NaN, NaN], [NaN, NaN]] + : [[lambda0$1, phi0], [lambda1, phi1]]; +}; + +var W0; +var W1; +var X0; +var Y0; +var Z0; +var X1; +var Y1; +var Z1; +var X2; +var Y2; +var Z2; +var lambda00$2; +var phi00$2; +var x0; +var y0; +var z0; // previous point + +var centroidStream = { + sphere: noop$1, + point: centroidPoint, + lineStart: centroidLineStart, + lineEnd: centroidLineEnd, + polygonStart: function() { + centroidStream.lineStart = centroidRingStart; + centroidStream.lineEnd = centroidRingEnd; + }, + polygonEnd: function() { + centroidStream.lineStart = centroidLineStart; + centroidStream.lineEnd = centroidLineEnd; + } +}; + +// Arithmetic mean of Cartesian vectors. +function centroidPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); +} + +function centroidPointCartesian(x, y, z) { + ++W0; + X0 += (x - X0) / W0; + Y0 += (y - Y0) / W0; + Z0 += (z - Z0) / W0; +} + +function centroidLineStart() { + centroidStream.point = centroidLinePointFirst; +} + +function centroidLinePointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidStream.point = centroidLinePoint; + centroidPointCartesian(x0, y0, z0); +} + +function centroidLinePoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +function centroidLineEnd() { + centroidStream.point = centroidPoint; +} + +// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, +// J. Applied Mechanics 42, 239 (1975). +function centroidRingStart() { + centroidStream.point = centroidRingPointFirst; +} + +function centroidRingEnd() { + centroidRingPoint(lambda00$2, phi00$2); + centroidStream.point = centroidPoint; +} + +function centroidRingPointFirst(lambda, phi) { + lambda00$2 = lambda, phi00$2 = phi; + lambda *= radians, phi *= radians; + centroidStream.point = centroidRingPoint; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidPointCartesian(x0, y0, z0); +} + +function centroidRingPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + cx = y0 * z - z0 * y, + cy = z0 * x - x0 * z, + cz = x0 * y - y0 * x, + m = sqrt(cx * cx + cy * cy + cz * cz), + w = asin(m), // line weight = angle + v = m && -w / m; // area weight multiplier + X2 += v * cx; + Y2 += v * cy; + Z2 += v * cz; + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +var centroid = function(object) { + W0 = W1 = + X0 = Y0 = Z0 = + X1 = Y1 = Z1 = + X2 = Y2 = Z2 = 0; + geoStream(object, centroidStream); + + var x = X2, + y = Y2, + z = Z2, + m = x * x + y * y + z * z; + + // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. + if (m < epsilon2$1) { + x = X1, y = Y1, z = Z1; + // If the feature has zero length, fall back to arithmetic mean of point vectors. + if (W1 < epsilon$2) x = X0, y = Y0, z = Z0; + m = x * x + y * y + z * z; + // If the feature still has an undefined ccentroid, then return. + if (m < epsilon2$1) return [NaN, NaN]; + } + + return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1]; +}; + +var constant$7 = function(x) { + return function() { + return x; + }; +}; + +var compose = function(a, b) { + + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + + return compose; +}; + +function rotationIdentity(lambda, phi) { + return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; +} + +rotationIdentity.invert = rotationIdentity; + +function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); +} + +function forwardRotationLambda(deltaLambda) { + return function(lambda, phi) { + return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; + }; +} + +function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; +} + +function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = cos$1(deltaPhi), + sinDeltaPhi = sin$1(deltaPhi), + cosDeltaGamma = cos$1(deltaGamma), + sinDeltaGamma = sin$1(deltaGamma); + + function rotation(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + asin(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } + + rotation.invert = function(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + asin(k * cosDeltaPhi - x * sinDeltaPhi) + ]; + }; + + return rotation; +} + +var rotation = function(rotate) { + rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + } + + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + }; + + return forward; +}; + +// Generates a circle centered at [0°, 0°], with a given radius and precision. +function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = cos$1(radius), + sinRadius = sin$1(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau$3; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); + stream.point(point[0], point[1]); + } +} + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3; +} + +var circle = function() { + var center = constant$7([0, 0]), + radius = constant$7(90), + precision = constant$7(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees$1, x[1] *= degrees$1; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius; + }; + + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision; + }; + + return circle; +}; + +var clipBuffer = function() { + var lines = [], + line; + return { + point: function(x, y) { + line.push([x, y]); + }, + lineStart: function() { + lines.push(line = []); + }, + lineEnd: noop$1, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + }, + result: function() { + var result = lines; + lines = []; + line = null; + return result; + } + }; +}; + +var clipLine = function(a, b, x0, y0, x1, y1) { + var ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; + if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; + return true; +}; + +var pointEqual = function(a, b) { + return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2; +}; + +function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous +} + +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. +var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; + + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n], x; + + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (pointEqual(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } + + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); + + if (!subject.length) return; + + clip.sort(compareIntersection); + link$1(subject); + link$1(clip); + + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } + + var start = subject[0], + points, + point; + + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); + } +}; + +function link$1(array) { + if (!(n = array.length)) return; + var n, + i = 0, + a = array[0], + b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; +} + +var clipMax = 1e9; +var clipMin = -clipMax; + +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? + +function clipExtent(x0, y0, x1, y1) { + + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } + + function corner(p, direction) { + return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3 + : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1 + : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } + + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } + + function comparePoint(a, b) { + var ca = corner(a, 1), + cb = corner(b, 1); + return ca !== cb ? ca - cb + : ca === 0 ? b[1] - a[1] + : ca === 1 ? a[0] - b[0] + : ca === 2 ? a[1] - b[1] + : b[0] - a[0]; + } + + return function(stream) { + var activeStream = stream, + bufferStream = clipBuffer(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; + + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; + + function point(x, y) { + if (visible(x, y)) activeStream.point(x, y); + } + + function polygonInside() { + var winding = 0; + + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } + else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } + } + } + + return winding; + } + + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } + + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = merge(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + clipPolygon(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); + } + activeStream = stream, segments = polygon = ring = null; + } + + function lineStart() { + clipStream.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) activeStream.lineEnd(); + } + + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (clipLine(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + + return clipStream; + }; +} + +var extent$1 = function() { + var x0 = 0, + y0 = 0, + x1 = 960, + y1 = 500, + cache, + cacheStream, + clip; + + return clip = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream); + }, + extent: function(_) { + return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; + } + }; +}; + +var sum$1 = adder(); + +var polygonContains = function(polygon, point) { + var lambda = point[0], + phi = point[1], + normal = [sin$1(lambda), -cos$1(lambda), 0], + angle = 0, + winding = 0; + + sum$1.reset(); + + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = point0[0], + phi0 = point0[1] / 2 + quarterPi, + sinPhi0 = sin$1(phi0), + cosPhi0 = cos$1(phi0); + + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = point1[0], + phi1 = point1[1] / 2 + quarterPi, + sinPhi1 = sin$1(phi1), + cosPhi1 = cos$1(phi1), + delta = lambda1 - lambda0, + sign$$1 = delta >= 0 ? 1 : -1, + absDelta = sign$$1 * delta, + antimeridian = absDelta > pi$3, + k = sinPhi0 * sinPhi1; + + sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); + angle += antimeridian ? delta + sign$$1 * tau$3 : delta; + + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = cartesianCross(cartesian(point0), cartesian(point1)); + cartesianNormalizeInPlace(arc); + var intersection = cartesianCross(normal, arc); + cartesianNormalizeInPlace(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } + } + } + } + + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. + + return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1); +}; + +var lengthSum = adder(); +var lambda0$2; +var sinPhi0$1; +var cosPhi0$1; + +var lengthStream = { + sphere: noop$1, + point: noop$1, + lineStart: lengthLineStart, + lineEnd: noop$1, + polygonStart: noop$1, + polygonEnd: noop$1 +}; + +function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; +} + +function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = noop$1; +} + +function lengthPointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); + lengthStream.point = lengthPoint; +} + +function lengthPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var sinPhi = sin$1(phi), + cosPhi = cos$1(phi), + delta = abs(lambda - lambda0$2), + cosDelta = cos$1(delta), + sinDelta = sin$1(delta), + x = cosPhi * sinDelta, + y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, + z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; + lengthSum.add(atan2(sqrt(x * x + y * y), z)); + lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; +} + +var length$1 = function(object) { + lengthSum.reset(); + geoStream(object, lengthStream); + return +lengthSum; +}; + +var coordinates = [null, null]; +var object$1 = {type: "LineString", coordinates: coordinates}; + +var distance = function(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return length$1(object$1); +}; + +var containsObjectType = { + Feature: function(object, point) { + return containsGeometry(object.geometry, point); + }, + FeatureCollection: function(object, point) { + var features = object.features, i = -1, n = features.length; + while (++i < n) if (containsGeometry(features[i].geometry, point)) return true; + return false; + } +}; + +var containsGeometryType = { + Sphere: function() { + return true; + }, + Point: function(object, point) { + return containsPoint(object.coordinates, point); + }, + MultiPoint: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsPoint(coordinates[i], point)) return true; + return false; + }, + LineString: function(object, point) { + return containsLine(object.coordinates, point); + }, + MultiLineString: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsLine(coordinates[i], point)) return true; + return false; + }, + Polygon: function(object, point) { + return containsPolygon(object.coordinates, point); + }, + MultiPolygon: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsPolygon(coordinates[i], point)) return true; + return false; + }, + GeometryCollection: function(object, point) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) if (containsGeometry(geometries[i], point)) return true; + return false; + } +}; + +function containsGeometry(geometry, point) { + return geometry && containsGeometryType.hasOwnProperty(geometry.type) + ? containsGeometryType[geometry.type](geometry, point) + : false; +} + +function containsPoint(coordinates, point) { + return distance(coordinates, point) === 0; +} + +function containsLine(coordinates, point) { + var ab = distance(coordinates[0], coordinates[1]), + ao = distance(coordinates[0], point), + ob = distance(point, coordinates[1]); + return ao + ob <= ab + epsilon$2; +} + +function containsPolygon(coordinates, point) { + return !!polygonContains(coordinates.map(ringRadians), pointRadians(point)); +} + +function ringRadians(ring) { + return ring = ring.map(pointRadians), ring.pop(), ring; +} + +function pointRadians(point) { + return [point[0] * radians, point[1] * radians]; +} + +var contains = function(object, point) { + return (object && containsObjectType.hasOwnProperty(object.type) + ? containsObjectType[object.type] + : containsGeometry)(object, point); +}; + +function graticuleX(y0, y1, dy) { + var y = sequence(y0, y1 - epsilon$2, dy).concat(y1); + return function(x) { return y.map(function(y) { return [x, y]; }); }; +} + +function graticuleY(x0, x1, dx) { + var x = sequence(x0, x1 - epsilon$2, dx).concat(x1); + return function(y) { return x.map(function(x) { return [x, y]; }); }; +} + +function graticule() { + var x1, x0, X1, X0, + y1, y0, Y1, Y0, + dx = 10, dy = dx, DX = 90, DY = 360, + x, y, X, Y, + precision = 2.5; + + function graticule() { + return {type: "MultiLineString", coordinates: lines()}; + } + + function lines() { + return sequence(ceil(X0 / DX) * DX, X1, DX).map(X) + .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) + .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x)) + .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y)); + } + + graticule.lines = function() { + return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; }); + }; + + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ + X(X0).concat( + Y(Y1).slice(1), + X(X1).reverse().slice(1), + Y(Y0).reverse().slice(1)) + ] + }; + }; + + graticule.extent = function(_) { + if (!arguments.length) return graticule.extentMinor(); + return graticule.extentMajor(_).extentMinor(_); + }; + + graticule.extentMajor = function(_) { + if (!arguments.length) return [[X0, Y0], [X1, Y1]]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + + graticule.extentMinor = function(_) { + if (!arguments.length) return [[x0, y0], [x1, y1]]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + + graticule.step = function(_) { + if (!arguments.length) return graticule.stepMinor(); + return graticule.stepMajor(_).stepMinor(_); + }; + + graticule.stepMajor = function(_) { + if (!arguments.length) return [DX, DY]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + + graticule.stepMinor = function(_) { + if (!arguments.length) return [dx, dy]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = graticuleX(y0, y1, 90); + y = graticuleY(x0, x1, precision); + X = graticuleX(Y0, Y1, 90); + Y = graticuleY(X0, X1, precision); + return graticule; + }; + + return graticule + .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]]) + .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]); +} + +function graticule10() { + return graticule()(); +} + +var interpolate$1 = function(a, b) { + var x0 = a[0] * radians, + y0 = a[1] * radians, + x1 = b[0] * radians, + y1 = b[1] * radians, + cy0 = cos$1(y0), + sy0 = sin$1(y0), + cy1 = cos$1(y1), + sy1 = sin$1(y1), + kx0 = cy0 * cos$1(x0), + ky0 = cy0 * sin$1(x0), + kx1 = cy1 * cos$1(x1), + ky1 = cy1 * sin$1(x1), + d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), + k = sin$1(d); + + var interpolate = d ? function(t) { + var B = sin$1(t *= d) / k, + A = sin$1(d - t) / k, + x = A * kx0 + B * kx1, + y = A * ky0 + B * ky1, + z = A * sy0 + B * sy1; + return [ + atan2(y, x) * degrees$1, + atan2(z, sqrt(x * x + y * y)) * degrees$1 + ]; + } : function() { + return [x0 * degrees$1, y0 * degrees$1]; + }; + + interpolate.distance = d; + + return interpolate; +}; + +var identity$4 = function(x) { + return x; +}; + +var areaSum$1 = adder(); +var areaRingSum$1 = adder(); +var x00; +var y00; +var x0$1; +var y0$1; + +var areaStream$1 = { + point: noop$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: function() { + areaStream$1.lineStart = areaRingStart$1; + areaStream$1.lineEnd = areaRingEnd$1; + }, + polygonEnd: function() { + areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1; + areaSum$1.add(abs(areaRingSum$1)); + areaRingSum$1.reset(); + }, + result: function() { + var area = areaSum$1 / 2; + areaSum$1.reset(); + return area; + } +}; + +function areaRingStart$1() { + areaStream$1.point = areaPointFirst$1; +} + +function areaPointFirst$1(x, y) { + areaStream$1.point = areaPoint$1; + x00 = x0$1 = x, y00 = y0$1 = y; +} + +function areaPoint$1(x, y) { + areaRingSum$1.add(y0$1 * x - x0$1 * y); + x0$1 = x, y0$1 = y; +} + +function areaRingEnd$1() { + areaPoint$1(x00, y00); +} + +var x0$2 = Infinity; +var y0$2 = x0$2; +var x1 = -x0$2; +var y1 = x1; + +var boundsStream$1 = { + point: boundsPoint$1, + lineStart: noop$1, + lineEnd: noop$1, + polygonStart: noop$1, + polygonEnd: noop$1, + result: function() { + var bounds = [[x0$2, y0$2], [x1, y1]]; + x1 = y1 = -(y0$2 = x0$2 = Infinity); + return bounds; + } +}; + +function boundsPoint$1(x, y) { + if (x < x0$2) x0$2 = x; + if (x > x1) x1 = x; + if (y < y0$2) y0$2 = y; + if (y > y1) y1 = y; +} + +// TODO Enforce positive area for exterior, negative area for interior? + +var X0$1 = 0; +var Y0$1 = 0; +var Z0$1 = 0; +var X1$1 = 0; +var Y1$1 = 0; +var Z1$1 = 0; +var X2$1 = 0; +var Y2$1 = 0; +var Z2$1 = 0; +var x00$1; +var y00$1; +var x0$3; +var y0$3; + +var centroidStream$1 = { + point: centroidPoint$1, + lineStart: centroidLineStart$1, + lineEnd: centroidLineEnd$1, + polygonStart: function() { + centroidStream$1.lineStart = centroidRingStart$1; + centroidStream$1.lineEnd = centroidRingEnd$1; + }, + polygonEnd: function() { + centroidStream$1.point = centroidPoint$1; + centroidStream$1.lineStart = centroidLineStart$1; + centroidStream$1.lineEnd = centroidLineEnd$1; + }, + result: function() { + var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] + : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] + : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] + : [NaN, NaN]; + X0$1 = Y0$1 = Z0$1 = + X1$1 = Y1$1 = Z1$1 = + X2$1 = Y2$1 = Z2$1 = 0; + return centroid; + } +}; + +function centroidPoint$1(x, y) { + X0$1 += x; + Y0$1 += y; + ++Z0$1; +} + +function centroidLineStart$1() { + centroidStream$1.point = centroidPointFirstLine; +} + +function centroidPointFirstLine(x, y) { + centroidStream$1.point = centroidPointLine; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidPointLine(x, y) { + var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidLineEnd$1() { + centroidStream$1.point = centroidPoint$1; +} + +function centroidRingStart$1() { + centroidStream$1.point = centroidPointFirstRing; +} + +function centroidRingEnd$1() { + centroidPointRing(x00$1, y00$1); +} + +function centroidPointFirstRing(x, y) { + centroidStream$1.point = centroidPointRing; + centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); +} + +function centroidPointRing(x, y) { + var dx = x - x0$3, + dy = y - y0$3, + z = sqrt(dx * dx + dy * dy); + + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + + z = y0$3 * x - x0$3 * y; + X2$1 += z * (x0$3 + x); + Y2$1 += z * (y0$3 + y); + Z2$1 += z * 3; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function PathContext(context) { + this._context = context; +} + +PathContext.prototype = { + _radius: 4.5, + pointRadius: function(_) { + return this._radius = _, this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._context.closePath(); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._context.moveTo(x, y); + this._point = 1; + break; + } + case 1: { + this._context.lineTo(x, y); + break; + } + default: { + this._context.moveTo(x + this._radius, y); + this._context.arc(x, y, this._radius, 0, tau$3); + break; + } + } + }, + result: noop$1 +}; + +var lengthSum$1 = adder(); +var lengthRing; +var x00$2; +var y00$2; +var x0$4; +var y0$4; + +var lengthStream$1 = { + point: noop$1, + lineStart: function() { + lengthStream$1.point = lengthPointFirst$1; + }, + lineEnd: function() { + if (lengthRing) lengthPoint$1(x00$2, y00$2); + lengthStream$1.point = noop$1; + }, + polygonStart: function() { + lengthRing = true; + }, + polygonEnd: function() { + lengthRing = null; + }, + result: function() { + var length = +lengthSum$1; + lengthSum$1.reset(); + return length; + } +}; + +function lengthPointFirst$1(x, y) { + lengthStream$1.point = lengthPoint$1; + x00$2 = x0$4 = x, y00$2 = y0$4 = y; +} + +function lengthPoint$1(x, y) { + x0$4 -= x, y0$4 -= y; + lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4)); + x0$4 = x, y0$4 = y; +} + +function PathString() { + this._string = []; +} + +PathString.prototype = { + _radius: 4.5, + _circle: circle$1(4.5), + pointRadius: function(_) { + if ((_ = +_) !== this._radius) this._radius = _, this._circle = null; + return this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._string.push("Z"); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._string.push("M", x, ",", y); + this._point = 1; + break; + } + case 1: { + this._string.push("L", x, ",", y); + break; + } + default: { + if (this._circle == null) this._circle = circle$1(this._radius); + this._string.push("M", x, ",", y, this._circle); + break; + } + } + }, + result: function() { + if (this._string.length) { + var result = this._string.join(""); + this._string = []; + return result; + } else { + return null; + } + } +}; + +function circle$1(radius) { + return "m0," + radius + + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + + "z"; +} + +var index$1 = function(projection, context) { + var pointRadius = 4.5, + projectionStream, + contextStream; + + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + geoStream(object, projectionStream(contextStream)); + } + return contextStream.result(); + } + + path.area = function(object) { + geoStream(object, projectionStream(areaStream$1)); + return areaStream$1.result(); + }; + + path.measure = function(object) { + geoStream(object, projectionStream(lengthStream$1)); + return lengthStream$1.result(); + }; + + path.bounds = function(object) { + geoStream(object, projectionStream(boundsStream$1)); + return boundsStream$1.result(); + }; + + path.centroid = function(object) { + geoStream(object, projectionStream(centroidStream$1)); + return centroidStream$1.result(); + }; + + path.projection = function(_) { + return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection; + }; + + path.context = function(_) { + if (!arguments.length) return context; + contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return path; + }; + + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + + return path.projection(projection).context(context); +}; + +var clip = function(pointVisible, clipLine, interpolate, start) { + return function(rotate, sink) { + var line = clipLine(sink), + rotatedStart = rotate.invert(start[0], start[1]), + ringBuffer = clipBuffer(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; + + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = merge(segments); + var startInside = polygonContains(polygon, rotatedStart); + if (segments.length) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + clipPolygon(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; + + function point(lambda, phi) { + var point = rotate(lambda, phi); + if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi); + } + + function pointLine(lambda, phi) { + var point = rotate(lambda, phi); + line.point(point[0], point[1]); + } + + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + var point = rotate(lambda, phi); + ringSink.point(point[0], point[1]); + } + + function ringStart() { + ringSink.lineStart(); + ring = []; + } + + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); + + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; + + ring.pop(); + polygon.push(ring); + ring = null; + + if (!n) return; + + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; + } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); + } + + return clip; + }; +}; + +function validSegment(segment) { + return segment.length > 1; +} + +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. +function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]); +} + +var clipAntimeridian = clip( + function() { return true; }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-pi$3, -halfPi$2] +); + +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. +function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function() { + stream.lineStart(); + clean = 1; + }, + point: function(lambda1, phi1) { + var sign1 = lambda1 > 0 ? pi$3 : -pi$3, + delta = abs(lambda1 - lambda0); + if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian + if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies + if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function() { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function() { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; +} + +function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = sin$1(lambda0 - lambda1); + return abs(sinLambda0Lambda1) > epsilon$2 + ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) + - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; +} + +function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * halfPi$2; + stream.point(-pi$3, phi); + stream.point(0, phi); + stream.point(pi$3, phi); + stream.point(pi$3, 0); + stream.point(pi$3, -phi); + stream.point(0, -phi); + stream.point(-pi$3, -phi); + stream.point(-pi$3, 0); + stream.point(-pi$3, phi); + } else if (abs(from[0] - to[0]) > epsilon$2) { + var lambda = from[0] < to[0] ? pi$3 : -pi$3; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } +} + +var clipCircle = function(radius, delta) { + var cr = cos$1(radius), + smallRadius = cr > 0, + notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case + + function interpolate(from, to, direction, stream) { + circleStream(stream, radius, delta, direction, from, to); + } + + function visible(lambda, phi) { + return cos$1(lambda) * cos$1(phi) > cr; + } + + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0; + if (!point0 && (v00 = v0 = v)) stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { + point1[0] += epsilon$2; + point1[1] += epsilon$2; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !pointEqual(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function() { + return clean | ((v00 && v0) << 1); + } + }; + } + + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = cartesian(a), + pb = cartesian(b); + + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = cartesianCross(pa, pb), + n2n2 = cartesianDot(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; + + // Two polar points. + if (!determinant) return !two && a; + + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = cartesianCross(n1, n2), + A = cartesianScale(n1, c1), + B = cartesianScale(n2, c2); + cartesianAddInPlace(A, B); + + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = cartesianDot(A, u), + uu = cartesianDot(u, u), + t2 = w * w - uu * (cartesianDot(A, A) - 1); + + if (t2 < 0) return; + + var t = sqrt(t2), + q = cartesianScale(u, (-w - t) / uu); + cartesianAddInPlace(q, A); + q = spherical(q); + + if (!two) return q; + + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; + + if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; + + var delta = lambda1 - lambda0, + polar = abs(delta - pi$3) < epsilon$2, + meridian = polar || delta < epsilon$2; + + if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; + + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = cartesianScale(u, (-w + t) / uu); + cartesianAddInPlace(q1, A); + return [q, spherical(q1)]; + } + } + + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : pi$3 - radius, + code = 0; + if (lambda < -r) code |= 1; // left + else if (lambda > r) code |= 2; // right + if (phi < -r) code |= 4; // below + else if (phi > r) code |= 8; // above + return code; + } + + return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]); +}; + +var transform = function(methods) { + return { + stream: transformer(methods) + }; +}; + +function transformer(methods) { + return function(stream) { + var s = new TransformStream; + for (var key in methods) s[key] = methods[key]; + s.stream = stream; + return s; + }; +} + +function TransformStream() {} + +TransformStream.prototype = { + constructor: TransformStream, + point: function(x, y) { this.stream.point(x, y); }, + sphere: function() { this.stream.sphere(); }, + lineStart: function() { this.stream.lineStart(); }, + lineEnd: function() { this.stream.lineEnd(); }, + polygonStart: function() { this.stream.polygonStart(); }, + polygonEnd: function() { this.stream.polygonEnd(); } +}; + +function fitExtent(projection, extent, object) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + clip = projection.clipExtent && projection.clipExtent(); + + projection + .scale(150) + .translate([0, 0]); + + if (clip != null) projection.clipExtent(null); + + geoStream(object, projection.stream(boundsStream$1)); + + var b = boundsStream$1.result(), + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + + if (clip != null) projection.clipExtent(clip); + + return projection + .scale(k * 150) + .translate([x, y]); +} + +function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); +} + +var maxDepth = 16; +var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) + +var resample = function(project, delta2) { + return +delta2 ? resample$1(project, delta2) : resampleNone(project); +}; + +function resampleNone(project) { + return transformer({ + point: function(x, y) { + x = project(x, y); + this.stream.point(x[0], x[1]); + } + }); +} + +function resample$1(project, delta2) { + + function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, + dy = y1 - y0, + d2 = dx * dx + dy * dy; + if (d2 > 4 * delta2 && depth--) { + var a = a0 + a1, + b = b0 + b1, + c = c0 + c1, + m = sqrt(a * a + b * b + c * c), + phi2 = asin(c /= m), + lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a), + p = project(lambda2, phi2), + x2 = p[0], + y2 = p[1], + dx2 = x2 - x0, + dy2 = y2 - y0, + dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > delta2 // perpendicular projected distance + || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end + || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); + } + } + } + return function(stream) { + var lambda00, x00, y00, a00, b00, c00, // first point + lambda0, x0, y0, a0, b0, c0; // previous point + + var resampleStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, + polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } + }; + + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + + function lineStart() { + x0 = NaN; + resampleStream.point = linePoint; + stream.lineStart(); + } + + function linePoint(lambda, phi) { + var c = cartesian([lambda, phi]), p = project(lambda, phi); + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + + function lineEnd() { + resampleStream.point = point; + stream.lineEnd(); + } + + function ringStart() { + lineStart(); + resampleStream.point = ringPoint; + resampleStream.lineEnd = ringEnd; + } + + function ringPoint(lambda, phi) { + linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resampleStream.point = linePoint; + } + + function ringEnd() { + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); + resampleStream.lineEnd = lineEnd; + lineEnd(); + } + + return resampleStream; + }; +} + +var transformRadians = transformer({ + point: function(x, y) { + this.stream.point(x * radians, y * radians); + } +}); + +function projection(project) { + return projectionMutator(function() { return project; })(); +} + +function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + dx, dy, lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate + theta = null, preclip = clipAntimeridian, // clip angle + x0 = null, y0, x1, y1, postclip = identity$4, // clip extent + delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision + cache, + cacheStream; + + function projection(point) { + point = projectRotate(point[0] * radians, point[1] * radians); + return [point[0] * k + dx, dy - point[1] * k]; + } + + function invert(point) { + point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); + return point && [point[0] * degrees$1, point[1] * degrees$1]; + } + + function projectTransform(x, y) { + return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; + } + + projection.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))); + }; + + projection.clipAngle = function(_) { + return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; + }; + + projection.clipExtent = function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + projection.scale = function(_) { + return arguments.length ? (k = +_, recenter()) : k; + }; + + projection.translate = function(_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; + + projection.center = function(_) { + return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; + }; + + projection.rotate = function(_) { + return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; + }; + + projection.precision = function(_) { + return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); + }; + + projection.fitExtent = function(extent, object) { + return fitExtent(projection, extent, object); + }; + + projection.fitSize = function(size, object) { + return fitSize(projection, size, object); + }; + + function recenter() { + projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); + var center = project(lambda, phi); + dx = x - center[0] * k; + dy = y + center[1] * k; + return reset(); + } + + function reset() { + cache = cacheStream = null; + return projection; + } + + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; +} + +function conicProjection(projectAt) { + var phi0 = 0, + phi1 = pi$3 / 3, + m = projectionMutator(projectAt), + p = m(phi0, phi1); + + p.parallels = function(_) { + return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; + }; + + return p; +} + +function cylindricalEqualAreaRaw(phi0) { + var cosPhi0 = cos$1(phi0); + + function forward(lambda, phi) { + return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; + } + + forward.invert = function(x, y) { + return [x / cosPhi0, asin(y * cosPhi0)]; + }; + + return forward; +} + +function conicEqualAreaRaw(y0, y1) { + var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; + + // Are the parallels symmetrical around the Equator? + if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; + + function project(x, y) { + var r = sqrt(c - 2 * n * sin$1(y)) / n; + return [r * sin$1(x *= n), r0 - r * cos$1(x)]; + } + + project.invert = function(x, y) { + var r0y = r0 - y; + return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; + }; + + return project; +} + +var conicEqualArea = function() { + return conicProjection(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); +}; + +var albers = function() { + return conicEqualArea() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); +}; + +// The projections must have mutually exclusive clip regions on the sphere, +// as this will avoid emitting interleaving lines and polygons. +function multiplex(streams) { + var n = streams.length; + return { + point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, + sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, + lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, + lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, + polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, + polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } + }; +} + +// A composite projection for the United States, configured by default for +// 960×500. The projection also works quite well at 960×600 if you change the +// scale to 1285 and adjust the translate accordingly. The set of standard +// parallels for each region comes from USGS, which is published here: +// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers +var albersUsa = function() { + var cache, + cacheStream, + lower48 = albers(), lower48Point, + alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 + hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 + point, pointStream = {point: function(x, y) { point = [x, y]; }}; + + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, + (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), point); + } + + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), + t = lower48.translate(), + x = (coordinates[0] - t[0]) / k, + y = (coordinates[1] - t[1]) / k; + return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii + : lower48).invert(coordinates); + }; + + albersUsa.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + }; + + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_); + return reset(); + }; + + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + + lower48Point = lower48 + .translate(_) + .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) + .stream(pointStream); + + alaskaPoint = alaska + .translate([x - 0.307 * k, y + 0.201 * k]) + .clipExtent([[x - 0.425 * k + epsilon$2, y + 0.120 * k + epsilon$2], [x - 0.214 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([[x - 0.214 * k + epsilon$2, y + 0.166 * k + epsilon$2], [x - 0.115 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + return reset(); + }; + + albersUsa.fitExtent = function(extent, object) { + return fitExtent(albersUsa, extent, object); + }; + + albersUsa.fitSize = function(size, object) { + return fitSize(albersUsa, size, object); + }; + + function reset() { + cache = cacheStream = null; + return albersUsa; + } + + return albersUsa.scale(1070); +}; + +function azimuthalRaw(scale) { + return function(x, y) { + var cx = cos$1(x), + cy = cos$1(y), + k = scale(cx * cy); + return [ + k * cy * sin$1(x), + k * sin$1(y) + ]; + } +} + +function azimuthalInvert(angle) { + return function(x, y) { + var z = sqrt(x * x + y * y), + c = angle(z), + sc = sin$1(c), + cc = cos$1(c); + return [ + atan2(x * sc, z * cc), + asin(z && y * sc / z) + ]; + } +} + +var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { + return sqrt(2 / (1 + cxcy)); +}); + +azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { + return 2 * asin(z / 2); +}); + +var azimuthalEqualArea = function() { + return projection(azimuthalEqualAreaRaw) + .scale(124.75) + .clipAngle(180 - 1e-3); +}; + +var azimuthalEquidistantRaw = azimuthalRaw(function(c) { + return (c = acos(c)) && c / sin$1(c); +}); + +azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { + return z; +}); + +var azimuthalEquidistant = function() { + return projection(azimuthalEquidistantRaw) + .scale(79.4188) + .clipAngle(180 - 1e-3); +}; + +function mercatorRaw(lambda, phi) { + return [lambda, log(tan((halfPi$2 + phi) / 2))]; +} + +mercatorRaw.invert = function(x, y) { + return [x, 2 * atan(exp(y)) - halfPi$2]; +}; + +var mercator = function() { + return mercatorProjection(mercatorRaw) + .scale(961 / tau$3); +}; + +function mercatorProjection(project) { + var m = projection(project), + center = m.center, + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + x0 = null, y0, x1, y1; // clip extent + + m.scale = function(_) { + return arguments.length ? (scale(_), reclip()) : scale(); + }; + + m.translate = function(_) { + return arguments.length ? (translate(_), reclip()) : translate(); + }; + + m.center = function(_) { + return arguments.length ? (center(_), reclip()) : center(); + }; + + m.clipExtent = function(_) { + return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + function reclip() { + var k = pi$3 * scale(), + t = m(rotation(m.rotate()).invert([0, 0])); + return clipExtent(x0 == null + ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw + ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] + : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); + } + + return reclip(); +} + +function tany(y) { + return tan((halfPi$2 + y) / 2); +} + +function conicConformalRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)), + f = cy0 * pow(tany(y0), n) / n; + + if (!n) return mercatorRaw; + + function project(x, y) { + if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; } + else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; } + var r = f / pow(tany(y), n); + return [r * sin$1(n * x), f - r * cos$1(n * x)]; + } + + project.invert = function(x, y) { + var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); + return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2]; + }; + + return project; +} + +var conicConformal = function() { + return conicProjection(conicConformalRaw) + .scale(109.5) + .parallels([30, 30]); +}; + +function equirectangularRaw(lambda, phi) { + return [lambda, phi]; +} + +equirectangularRaw.invert = equirectangularRaw; + +var equirectangular = function() { + return projection(equirectangularRaw) + .scale(152.63); +}; + +function conicEquidistantRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), + g = cy0 / n + y0; + + if (abs(n) < epsilon$2) return equirectangularRaw; + + function project(x, y) { + var gy = g - y, nx = n * x; + return [gy * sin$1(nx), g - gy * cos$1(nx)]; + } + + project.invert = function(x, y) { + var gy = g - y; + return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)]; + }; + + return project; +} + +var conicEquidistant = function() { + return conicProjection(conicEquidistantRaw) + .scale(131.154) + .center([0, 13.9389]); +}; + +function gnomonicRaw(x, y) { + var cy = cos$1(y), k = cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; +} + +gnomonicRaw.invert = azimuthalInvert(atan); + +var gnomonic = function() { + return projection(gnomonicRaw) + .scale(144.049) + .clipAngle(60); +}; + +function scaleTranslate(kx, ky, tx, ty) { + return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({ + point: function(x, y) { + this.stream.point(x * kx + tx, y * ky + ty); + } + }); +} + +var identity$5 = function() { + var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$4, // scale, translate and reflect + x0 = null, y0, x1, y1, clip = identity$4, // clip extent + cache, + cacheStream, + projection; + + function reset() { + cache = cacheStream = null; + return projection; + } + + return projection = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream)); + }, + clipExtent: function(_) { + return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }, + scale: function(_) { + return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k; + }, + translate: function(_) { + return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; + }, + reflectX: function(_) { + return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0; + }, + reflectY: function(_) { + return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0; + }, + fitExtent: function(extent, object) { + return fitExtent(projection, extent, object); + }, + fitSize: function(size, object) { + return fitSize(projection, size, object); + } + }; +}; + +function orthographicRaw(x, y) { + return [cos$1(y) * sin$1(x), sin$1(y)]; +} + +orthographicRaw.invert = azimuthalInvert(asin); + +var orthographic = function() { + return projection(orthographicRaw) + .scale(249.5) + .clipAngle(90 + epsilon$2); +}; + +function stereographicRaw(x, y) { + var cy = cos$1(y), k = 1 + cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; +} + +stereographicRaw.invert = azimuthalInvert(function(z) { + return 2 * atan(z); +}); + +var stereographic = function() { + return projection(stereographicRaw) + .scale(250) + .clipAngle(142); +}; + +function transverseMercatorRaw(lambda, phi) { + return [log(tan((halfPi$2 + phi) / 2)), -lambda]; +} + +transverseMercatorRaw.invert = function(x, y) { + return [-y, 2 * atan(exp(x)) - halfPi$2]; +}; + +var transverseMercator = function() { + var m = mercatorProjection(transverseMercatorRaw), + center = m.center, + rotate = m.rotate; + + m.center = function(_) { + return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); + }; + + m.rotate = function(_) { + return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); + }; + + return rotate([0, 0, 90]) + .scale(159.155); +}; + +function defaultSeparation(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +function meanX(children) { + return children.reduce(meanXReduce, 0) / children.length; +} + +function meanXReduce(x, c) { + return x + c.x; +} + +function maxY(children) { + return 1 + children.reduce(maxYReduce, 0); +} + +function maxYReduce(y, c) { + return Math.max(y, c.y); +} + +function leafLeft(node) { + var children; + while (children = node.children) node = children[0]; + return node; +} + +function leafRight(node) { + var children; + while (children = node.children) node = children[children.length - 1]; + return node; +} + +var cluster = function() { + var separation = defaultSeparation, + dx = 1, + dy = 1, + nodeSize = false; + + function cluster(root) { + var previousNode, + x = 0; + + // First walk, computing the initial x & y values. + root.eachAfter(function(node) { + var children = node.children; + if (children) { + node.x = meanX(children); + node.y = maxY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + + var left = leafLeft(root), + right = leafRight(root), + x0 = left.x - separation(left, right) / 2, + x1 = right.x + separation(right, left) / 2; + + // Second walk, normalizing x & y to the desired size. + return root.eachAfter(nodeSize ? function(node) { + node.x = (node.x - root.x) * dx; + node.y = (root.y - node.y) * dy; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * dx; + node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; + }); + } + + cluster.separation = function(x) { + return arguments.length ? (separation = x, cluster) : separation; + }; + + cluster.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); + }; + + cluster.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + }; + + return cluster; +}; + +function count(node) { + var sum = 0, + children = node.children, + i = children && children.length; + if (!i) sum = 1; + else while (--i >= 0) sum += children[i].value; + node.value = sum; +} + +var node_count = function() { + return this.eachAfter(count); +}; + +var node_each = function(callback) { + var node = this, current, next = [node], children, i, n; + do { + current = next.reverse(), next = []; + while (node = current.pop()) { + callback(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } + } + } while (next.length); + return this; +}; + +var node_eachBefore = function(callback) { + var node = this, nodes = [node], children, i; + while (node = nodes.pop()) { + callback(node), children = node.children; + if (children) for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } + } + return this; +}; + +var node_eachAfter = function(callback) { + var node = this, nodes = [node], next = [], children, i, n; + while (node = nodes.pop()) { + next.push(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } + } + while (node = next.pop()) { + callback(node); + } + return this; +}; + +var node_sum = function(value) { + return this.eachAfter(function(node) { + var sum = +value(node.data) || 0, + children = node.children, + i = children && children.length; + while (--i >= 0) sum += children[i].value; + node.value = sum; + }); +}; + +var node_sort = function(compare) { + return this.eachBefore(function(node) { + if (node.children) { + node.children.sort(compare); + } + }); +}; + +var node_path = function(end) { + var start = this, + ancestor = leastCommonAncestor(start, end), + nodes = [start]; + while (start !== ancestor) { + start = start.parent; + nodes.push(start); + } + var k = nodes.length; + while (end !== ancestor) { + nodes.splice(k, 0, end); + end = end.parent; + } + return nodes; +}; + +function leastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = a.ancestors(), + bNodes = b.ancestors(), + c = null; + a = aNodes.pop(); + b = bNodes.pop(); + while (a === b) { + c = a; + a = aNodes.pop(); + b = bNodes.pop(); + } + return c; +} + +var node_ancestors = function() { + var node = this, nodes = [node]; + while (node = node.parent) { + nodes.push(node); + } + return nodes; +}; + +var node_descendants = function() { + var nodes = []; + this.each(function(node) { + nodes.push(node); + }); + return nodes; +}; + +var node_leaves = function() { + var leaves = []; + this.eachBefore(function(node) { + if (!node.children) { + leaves.push(node); + } + }); + return leaves; +}; + +var node_links = function() { + var root = this, links = []; + root.each(function(node) { + if (node !== root) { // Don’t include the root’s parent, if any. + links.push({source: node.parent, target: node}); + } + }); + return links; +}; + +function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), + node, + nodes = [root], + child, + childs, + i, + n; + + if (children == null) children = defaultChildren; + + while (node = nodes.pop()) { + if (valued) node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new Node(childs[i])); + child.parent = node; + child.depth = node.depth + 1; + } + } + } + + return root.eachBefore(computeHeight); +} + +function node_copy() { + return hierarchy(this).eachBefore(copyData); +} + +function defaultChildren(d) { + return d.children; +} + +function copyData(node) { + node.data = node.data.data; +} + +function computeHeight(node) { + var height = 0; + do node.height = height; + while ((node = node.parent) && (node.height < ++height)); +} + +function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; +} + +Node.prototype = hierarchy.prototype = { + constructor: Node, + count: node_count, + each: node_each, + eachAfter: node_eachAfter, + eachBefore: node_eachBefore, + sum: node_sum, + sort: node_sort, + path: node_path, + ancestors: node_ancestors, + descendants: node_descendants, + leaves: node_leaves, + links: node_links, + copy: node_copy +}; + +function Node$2(value) { + this._ = value; + this.next = null; +} + +var shuffle$1 = function(array) { + var i, + n = (array = array.slice()).length, + head = null, + node = head; + + while (n) { + var next = new Node$2(array[n - 1]); + if (node) node = node.next = next; + else node = head = next; + array[i] = array[--n]; + } + + return { + head: head, + tail: node + }; +}; + +var enclose = function(circles) { + return encloseN(shuffle$1(circles), []); +}; + +function encloses(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r - b.r; + return dr * dr + 1e-6 > dx * dx + dy * dy; +} + +// Returns the smallest circle that contains circles L and intersects circles B. +function encloseN(L, B) { + var circle, + l0 = null, + l1 = L.head, + l2, + p1; + + switch (B.length) { + case 1: circle = enclose1(B[0]); break; + case 2: circle = enclose2(B[0], B[1]); break; + case 3: circle = enclose3(B[0], B[1], B[2]); break; + } + + while (l1) { + p1 = l1._, l2 = l1.next; + if (!circle || !encloses(circle, p1)) { + + // Temporarily truncate L before l1. + if (l0) L.tail = l0, l0.next = null; + else L.head = L.tail = null; + + B.push(p1); + circle = encloseN(L, B); // Note: reorders L! + B.pop(); + + // Move l1 to the front of L and reconnect the truncated list L. + if (L.head) l1.next = L.head, L.head = l1; + else l1.next = null, L.head = L.tail = l1; + l0 = L.tail, l0.next = l2; + + } else { + l0 = l1; + } + l1 = l2; + } + + L.tail = l0; + return circle; +} + +function enclose1(a) { + return { + x: a.x, + y: a.y, + r: a.r + }; +} + +function enclose2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 + }; +} + +function enclose3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = 2 * (x1 - x2), + b2 = 2 * (y1 - y2), + c2 = 2 * (r2 - r1), + d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2, + a3 = 2 * (x1 - x3), + b3 = 2 * (y1 - y3), + c3 = 2 * (r3 - r1), + d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / ab - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / ab - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (xa * xb + ya * yb + r1), + C = xa * xa + ya * ya - r1 * r1, + r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); + return { + x: xa + xb * r + x1, + y: ya + yb * r + y1, + r: r + }; +} + +function place(a, b, c) { + var ax = a.x, + ay = a.y, + da = b.r + c.r, + db = a.r + c.r, + dx = b.x - ax, + dy = b.y - ay, + dc = dx * dx + dy * dy; + if (dc) { + var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), + y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = ax + x * dx + y * dy; + c.y = ay + x * dy - y * dx; + } else { + c.x = ax + db; + c.y = ay; + } +} + +function intersects(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r + b.r; + return dr * dr - 1e-6 > dx * dx + dy * dy; +} + +function distance2(node, x, y) { + var a = node._, + b = node.next._, + ab = a.r + b.r, + dx = (a.x * b.r + b.x * a.r) / ab - x, + dy = (a.y * b.r + b.y * a.r) / ab - y; + return dx * dx + dy * dy; +} + +function Node$1(circle) { + this._ = circle; + this.next = null; + this.previous = null; +} + +function packEnclose(circles) { + if (!(n = circles.length)) return 0; + + var a, b, c, n; + + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the weighted centroid. + var aa = a.r * a.r, + ba = b.r * b.r, + ca = c.r * c.r, + oa = aa + ba + ca, + ox = aa * a.x + ba * b.x + ca * c.x, + oy = aa * a.y + ba * b.y + ca * c.y, + cx, cy, i, j, k, sj, sk; + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node$1(c); + + // Find the closest intersecting circle on the front-chain, if any. + // “Closeness” is determined by linear distance along the front-chain. + // “Ahead” or “behind” is likewise determined by linear distance. + j = b.next, k = a.previous, sj = b._.r, sk = a._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + sj += j._.r, j = j.next; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + sk += k._.r, k = k.previous; + } + } while (j !== k.next); + + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; + + // Update the weighted centroid. + oa += ca = c._.r * c._.r; + ox += ca * c._.x; + oy += ca * c._.y; + + // Compute the new closest circle pair to the centroid. + aa = distance2(a, cx = ox / oa, cy = oy / oa); + while ((c = c.next) !== b) { + if ((ca = distance2(c, cx, cy)) < aa) { + a = c, aa = ca; + } + } + b = a.next; + } + + // Compute the enclosing circle of the front chain. + a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); + + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; + + return c.r; +} + +var siblings = function(circles) { + packEnclose(circles); + return circles; +}; + +function optional(f) { + return f == null ? null : required(f); +} + +function required(f) { + if (typeof f !== "function") throw new Error; + return f; +} + +function constantZero() { + return 0; +} + +var constant$8 = function(x) { + return function() { + return x; + }; +}; + +function defaultRadius$1(d) { + return Math.sqrt(d.value); +} + +var index$2 = function() { + var radius = null, + dx = 1, + dy = 1, + padding = constantZero; + + function pack(root) { + root.x = dx / 2, root.y = dy / 2; + if (radius) { + root.eachBefore(radiusLeaf(radius)) + .eachAfter(packChildren(padding, 0.5)) + .eachBefore(translateChild(1)); + } else { + root.eachBefore(radiusLeaf(defaultRadius$1)) + .eachAfter(packChildren(constantZero, 1)) + .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) + .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); + } + return root; + } + + pack.radius = function(x) { + return arguments.length ? (radius = optional(x), pack) : radius; + }; + + pack.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; + }; + + pack.padding = function(x) { + return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding; + }; + + return pack; +}; + +function radiusLeaf(radius) { + return function(node) { + if (!node.children) { + node.r = Math.max(0, +radius(node) || 0); + } + }; +} + +function packChildren(padding, k) { + return function(node) { + if (children = node.children) { + var children, + i, + n = children.length, + r = padding(node) * k || 0, + e; + + if (r) for (i = 0; i < n; ++i) children[i].r += r; + e = packEnclose(children); + if (r) for (i = 0; i < n; ++i) children[i].r -= r; + node.r = e + r; + } + }; +} + +function translateChild(k) { + return function(node) { + var parent = node.parent; + node.r *= k; + if (parent) { + node.x = parent.x + k * node.x; + node.y = parent.y + k * node.y; + } + }; +} + +var roundNode = function(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); +}; + +var treemapDice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; + + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } +}; + +var partition = function() { + var dx = 1, + dy = 1, + padding = 0, + round = false; + + function partition(root) { + var n = root.height + 1; + root.x0 = + root.y0 = padding; + root.x1 = dx; + root.y1 = dy / n; + root.eachBefore(positionNode(dy, n)); + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(dy, n) { + return function(node) { + if (node.children) { + treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); + } + var x0 = node.x0, + y0 = node.y0, + x1 = node.x1 - padding, + y1 = node.y1 - padding; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + }; + } + + partition.round = function(x) { + return arguments.length ? (round = !!x, partition) : round; + }; + + partition.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; + }; + + partition.padding = function(x) { + return arguments.length ? (padding = +x, partition) : padding; + }; + + return partition; +}; + +var keyPrefix$1 = "$"; +var preroot = {depth: -1}; +var ambiguous = {}; + +function defaultId(d) { + return d.id; +} + +function defaultParentId(d) { + return d.parentId; +} + +var stratify = function() { + var id = defaultId, + parentId = defaultParentId; + + function stratify(data) { + var d, + i, + n = data.length, + root, + parent, + node, + nodes = new Array(n), + nodeId, + nodeKey, + nodeByKey = {}; + + for (i = 0; i < n; ++i) { + d = data[i], node = nodes[i] = new Node(d); + if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { + nodeKey = keyPrefix$1 + (node.id = nodeId); + nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; + } + } + + for (i = 0; i < n; ++i) { + node = nodes[i], nodeId = parentId(data[i], i, data); + if (nodeId == null || !(nodeId += "")) { + if (root) throw new Error("multiple roots"); + root = node; + } else { + parent = nodeByKey[keyPrefix$1 + nodeId]; + if (!parent) throw new Error("missing: " + nodeId); + if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); + if (parent.children) parent.children.push(node); + else parent.children = [node]; + node.parent = parent; + } + } + + if (!root) throw new Error("no root"); + root.parent = preroot; + root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); + root.parent = null; + if (n > 0) throw new Error("cycle"); + + return root; + } + + stratify.id = function(x) { + return arguments.length ? (id = required(x), stratify) : id; + }; + + stratify.parentId = function(x) { + return arguments.length ? (parentId = required(x), stratify) : parentId; + }; + + return stratify; +}; + +function defaultSeparation$1(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +// function radialSeparation(a, b) { +// return (a.parent === b.parent ? 1 : 2) / a.depth; +// } + +// This function is used to traverse the left contour of a subtree (or +// subforest). It returns the successor of v on this contour. This successor is +// either given by the leftmost child of v or by the thread of v. The function +// returns null if and only if v is on the highest level of its subtree. +function nextLeft(v) { + var children = v.children; + return children ? children[0] : v.t; +} + +// This function works analogously to nextLeft. +function nextRight(v) { + var children = v.children; + return children ? children[children.length - 1] : v.t; +} + +// Shifts the current subtree rooted at w+. This is done by increasing +// prelim(w+) and mod(w+) by shift. +function moveSubtree(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; +} + +// All other shifts, applied to the smaller subtrees between w- and w+, are +// performed by this function. To prepare the shifts, we have to adjust +// change(w+), shift(w+), and change(w-). +function executeShifts(v) { + var shift = 0, + change = 0, + children = v.children, + i = children.length, + w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } +} + +// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, +// returns the specified (default) ancestor. +function nextAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; +} + +function TreeNode(node, i) { + this._ = node; + this.parent = null; + this.children = null; + this.A = null; // default ancestor + this.a = this; // ancestor + this.z = 0; // prelim + this.m = 0; // mod + this.c = 0; // change + this.s = 0; // shift + this.t = null; // thread + this.i = i; // number +} + +TreeNode.prototype = Object.create(Node.prototype); + +function treeRoot(root) { + var tree = new TreeNode(root, 0), + node, + nodes = [tree], + child, + children, + i, + n; + + while (node = nodes.pop()) { + if (children = node._.children) { + node.children = new Array(n = children.length); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + child.parent = node; + } + } + } + + (tree.parent = new TreeNode(null, 0)).children = [tree]; + return tree; +} + +// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm +var tree = function() { + var separation = defaultSeparation$1, + dx = 1, + dy = 1, + nodeSize = null; + + function tree(root) { + var t = treeRoot(root); + + // Compute the layout using Buchheim et al.’s algorithm. + t.eachAfter(firstWalk), t.parent.m = -t.z; + t.eachBefore(secondWalk); + + // If a fixed node size is specified, scale x and y. + if (nodeSize) root.eachBefore(sizeNode); + + // If a fixed tree size is specified, scale x and y based on the extent. + // Compute the left-most, right-most, and depth-most nodes for extents. + else { + var left = root, + right = root, + bottom = root; + root.eachBefore(function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var s = left === right ? 1 : separation(left, right) / 2, + tx = s - left.x, + kx = dx / (right.x + s + tx), + ky = dy / (bottom.depth || 1); + root.eachBefore(function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + + return root; + } + + // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is + // applied recursively to the children of v, as well as the function + // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the + // node v is placed to the midpoint of its outermost children. + function firstWalk(v) { + var children = v.children, + siblings = v.parent.children, + w = v.i ? siblings[v.i - 1] : null; + if (children) { + executeShifts(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + + // Computes all real x-coordinates by summing up the modifiers recursively. + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + + // The core of the algorithm. Here, a new subtree is combined with the + // previous subtrees. Threads are used to traverse the inside and outside + // contours of the left and right subtree up to the highest common level. The + // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the + // superscript o means outside and i means inside, the subscript - means left + // subtree and + means right subtree. For summing up the modifiers along the + // contour, we use respective variables si+, si-, so-, and so+. Whenever two + // nodes of the inside contours conflict, we compute the left one of the + // greatest uncommon ancestors using the function ANCESTOR and call MOVE + // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. + // Finally, we add a new thread (if necessary). + function apportion(v, w, ancestor) { + if (w) { + var vip = v, + vop = v, + vim = w, + vom = vip.parent.children[0], + sip = vip.m, + sop = vop.m, + sim = vim.m, + som = vom.m, + shift; + while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { + vom = nextLeft(vom); + vop = nextRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + moveSubtree(nextAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !nextRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !nextLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + + function sizeNode(node) { + node.x *= dx; + node.y = node.depth * dy; + } + + tree.separation = function(x) { + return arguments.length ? (separation = x, tree) : separation; + }; + + tree.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); + }; + + tree.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); + }; + + return tree; +}; + +var treemapSlice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; + + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; + } +}; + +var phi = (1 + Math.sqrt(5)) / 2; + +function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1 = 0, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; + + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; + + // Find the next non-empty node. + do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); + minValue = maxValue = sumValue; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); + + // Keep adding nodes while the aspect ratio maintains or improves. + for (; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) minValue = nodeValue; + if (nodeValue > maxValue) maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { sumValue -= nodeValue; break; } + minRatio = newRatio; + } + + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; + } + + return rows; +} + +var squarify = ((function custom(ratio) { + + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } + + squarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return squarify; +}))(phi); + +var index$3 = function() { + var tile = squarify, + round = false, + dx = 1, + dy = 1, + paddingStack = [0], + paddingInner = constantZero, + paddingTop = constantZero, + paddingRight = constantZero, + paddingBottom = constantZero, + paddingLeft = constantZero; + + function treemap(root) { + root.x0 = + root.y0 = 0; + root.x1 = dx; + root.y1 = dy; + root.eachBefore(positionNode); + paddingStack = [0]; + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(node) { + var p = paddingStack[node.depth], + x0 = node.x0 + p, + y0 = node.y0 + p, + x1 = node.x1 - p, + y1 = node.y1 - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + if (node.children) { + p = paddingStack[node.depth + 1] = paddingInner(node) / 2; + x0 += paddingLeft(node) - p; + y0 += paddingTop(node) - p; + x1 -= paddingRight(node) - p; + y1 -= paddingBottom(node) - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + tile(node, x0, y0, x1, y1); + } + } + + treemap.round = function(x) { + return arguments.length ? (round = !!x, treemap) : round; + }; + + treemap.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; + }; + + treemap.tile = function(x) { + return arguments.length ? (tile = required(x), treemap) : tile; + }; + + treemap.padding = function(x) { + return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); + }; + + treemap.paddingInner = function(x) { + return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner; + }; + + treemap.paddingOuter = function(x) { + return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); + }; + + treemap.paddingTop = function(x) { + return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop; + }; + + treemap.paddingRight = function(x) { + return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight; + }; + + treemap.paddingBottom = function(x) { + return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom; + }; + + treemap.paddingLeft = function(x) { + return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft; + }; + + return treemap; +}; + +var binary = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + i, n = nodes.length, + sum, sums = new Array(n + 1); + + for (sums[0] = sum = i = 0; i < n; ++i) { + sums[i + 1] = sum += nodes[i].value; + } + + partition(0, n, parent.value, x0, y0, x1, y1); + + function partition(i, j, value, x0, y0, x1, y1) { + if (i >= j - 1) { + var node = nodes[i]; + node.x0 = x0, node.y0 = y0; + node.x1 = x1, node.y1 = y1; + return; + } + + var valueOffset = sums[i], + valueTarget = (value / 2) + valueOffset, + k = i + 1, + hi = j - 1; + + while (k < hi) { + var mid = k + hi >>> 1; + if (sums[mid] < valueTarget) k = mid + 1; + else hi = mid; + } + + if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k; + + var valueLeft = sums[k] - valueOffset, + valueRight = value - valueLeft; + + if ((x1 - x0) > (y1 - y0)) { + var xk = (x0 * valueRight + x1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, xk, y1); + partition(k, j, valueRight, xk, y0, x1, y1); + } else { + var yk = (y0 * valueRight + y1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, x1, yk); + partition(k, j, valueRight, x0, yk, x1, y1); + } + } +}; + +var sliceDice = function(parent, x0, y0, x1, y1) { + (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); +}; + +var resquarify = ((function custom(ratio) { + + function resquarify(parent, x0, y0, x1, y1) { + if ((rows = parent._squarify) && (rows.ratio === ratio)) { + var rows, + row, + nodes, + i, + j = -1, + n, + m = rows.length, + value = parent.value; + + while (++j < m) { + row = rows[j], nodes = row.children; + for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; + if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); + else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); + value -= row.value; + } + } else { + parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); + rows.ratio = ratio; + } + } + + resquarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return resquarify; +}))(phi); + +var area$1 = function(polygon) { + var i = -1, + n = polygon.length, + a, + b = polygon[n - 1], + area = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + + return area / 2; +}; + +var centroid$1 = function(polygon) { + var i = -1, + n = polygon.length, + x = 0, + y = 0, + a, + b = polygon[n - 1], + c, + k = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + k += c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + + return k *= 3, [x / k, y / k]; +}; + +// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of +// the 3D cross product in a quadrant I Cartesian coordinate system (+x is +// right, +y is up). Returns a positive value if ABC is counter-clockwise, +// negative if clockwise, and zero if the points are collinear. +var cross$1 = function(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); +}; + +function lexicographicOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; +} + +// Computes the upper convex hull per the monotone chain algorithm. +// Assumes points.length >= 3, is sorted by x, unique in y. +// Returns an array of indices into points in left-to-right order. +function computeUpperHullIndexes(points) { + var n = points.length, + indexes = [0, 1], + size = 2; + + for (var i = 2; i < n; ++i) { + while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; + indexes[size++] = i; + } + + return indexes.slice(0, size); // remove popped points +} + +var hull = function(points) { + if ((n = points.length) < 3) return null; + + var i, + n, + sortedPoints = new Array(n), + flippedPoints = new Array(n); + + for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; + sortedPoints.sort(lexicographicOrder); + for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; + + var upperIndexes = computeUpperHullIndexes(sortedPoints), + lowerIndexes = computeUpperHullIndexes(flippedPoints); + + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] === upperIndexes[0], + skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], + hull = []; + + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); + for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + + return hull; +}; + +var contains$1 = function(polygon, point) { + var n = polygon.length, + p = polygon[n - 1], + x = point[0], y = point[1], + x0 = p[0], y0 = p[1], + x1, y1, + inside = false; + + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; + x0 = x1, y0 = y1; + } + + return inside; +}; + +var length$2 = function(polygon) { + var i = -1, + n = polygon.length, + b = polygon[n - 1], + xa, + ya, + xb = b[0], + yb = b[1], + perimeter = 0; + + while (++i < n) { + xa = xb; + ya = yb; + b = polygon[i]; + xb = b[0]; + yb = b[1]; + xa -= xb; + ya -= yb; + perimeter += Math.sqrt(xa * xa + ya * ya); + } + + return perimeter; +}; + +var slice$3 = [].slice; + +var noabort = {}; + +function Queue(size) { + this._size = size; + this._call = + this._error = null; + this._tasks = []; + this._data = []; + this._waiting = + this._active = + this._ended = + this._start = 0; // inside a synchronous task callback? +} + +Queue.prototype = queue.prototype = { + constructor: Queue, + defer: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("defer after await"); + if (this._error != null) return this; + var t = slice$3.call(arguments, 1); + t.push(callback); + ++this._waiting, this._tasks.push(t); + poke$1(this); + return this; + }, + abort: function() { + if (this._error == null) abort(this, new Error("abort")); + return this; + }, + await: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("multiple await"); + this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; + maybeNotify(this); + return this; + }, + awaitAll: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("multiple await"); + this._call = callback; + maybeNotify(this); + return this; + } +}; + +function poke$1(q) { + if (!q._start) { + try { start$1(q); } // let the current task complete + catch (e) { + if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously + else if (!q._data) throw e; // await callback errored synchronously + } + } +} + +function start$1(q) { + while (q._start = q._waiting && q._active < q._size) { + var i = q._ended + q._active, + t = q._tasks[i], + j = t.length - 1, + c = t[j]; + t[j] = end(q, i); + --q._waiting, ++q._active; + t = c.apply(null, t); + if (!q._tasks[i]) continue; // task finished synchronously + q._tasks[i] = t || noabort; + } +} + +function end(q, i) { + return function(e, r) { + if (!q._tasks[i]) return; // ignore multiple callbacks + --q._active, ++q._ended; + q._tasks[i] = null; + if (q._error != null) return; // ignore secondary errors + if (e != null) { + abort(q, e); + } else { + q._data[i] = r; + if (q._waiting) poke$1(q); + else maybeNotify(q); + } + }; +} + +function abort(q, e) { + var i = q._tasks.length, t; + q._error = e; // ignore active callbacks + q._data = undefined; // allow gc + q._waiting = NaN; // prevent starting + + while (--i >= 0) { + if (t = q._tasks[i]) { + q._tasks[i] = null; + if (t.abort) { + try { t.abort(); } + catch (e) { /* ignore */ } + } + } + } + + q._active = NaN; // allow notification + maybeNotify(q); +} + +function maybeNotify(q) { + if (!q._active && q._call) { + var d = q._data; + q._data = undefined; // allow gc + q._call(q._error, d); + } +} + +function queue(concurrency) { + if (concurrency == null) concurrency = Infinity; + else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency"); + return new Queue(concurrency); +} + +var defaultSource$1 = function() { + return Math.random(); +}; + +var uniform = ((function sourceRandomUniform(source) { + function randomUniform(min, max) { + min = min == null ? 0 : +min; + max = max == null ? 1 : +max; + if (arguments.length === 1) max = min, min = 0; + else max -= min; + return function() { + return source() * max + min; + }; + } + + randomUniform.source = sourceRandomUniform; + + return randomUniform; +}))(defaultSource$1); + +var normal = ((function sourceRandomNormal(source) { + function randomNormal(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function() { + var y; + + // If available, use the second previously-generated uniform random. + if (x != null) y = x, x = null; + + // Otherwise, generate a new x and y. + else do { + x = source() * 2 - 1; + y = source() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + }; + } + + randomNormal.source = sourceRandomNormal; + + return randomNormal; +}))(defaultSource$1); + +var logNormal = ((function sourceRandomLogNormal(source) { + function randomLogNormal() { + var randomNormal = normal.source(source).apply(this, arguments); + return function() { + return Math.exp(randomNormal()); + }; + } + + randomLogNormal.source = sourceRandomLogNormal; + + return randomLogNormal; +}))(defaultSource$1); + +var irwinHall = ((function sourceRandomIrwinHall(source) { + function randomIrwinHall(n) { + return function() { + for (var sum = 0, i = 0; i < n; ++i) sum += source(); + return sum; + }; + } + + randomIrwinHall.source = sourceRandomIrwinHall; + + return randomIrwinHall; +}))(defaultSource$1); + +var bates = ((function sourceRandomBates(source) { + function randomBates(n) { + var randomIrwinHall = irwinHall.source(source)(n); + return function() { + return randomIrwinHall() / n; + }; + } + + randomBates.source = sourceRandomBates; + + return randomBates; +}))(defaultSource$1); + +var exponential$1 = ((function sourceRandomExponential(source) { + function randomExponential(lambda) { + return function() { + return -Math.log(1 - source()) / lambda; + }; + } + + randomExponential.source = sourceRandomExponential; + + return randomExponential; +}))(defaultSource$1); + +var request = function(url, callback) { + var request, + event = dispatch("beforesend", "progress", "load", "error"), + mimeType, + headers = map$1(), + xhr = new XMLHttpRequest, + user = null, + password = null, + response, + responseType, + timeout = 0; + + // If IE does not support CORS, use XDomainRequest. + if (typeof XDomainRequest !== "undefined" + && !("withCredentials" in xhr) + && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; + + "onload" in xhr + ? xhr.onload = xhr.onerror = xhr.ontimeout = respond + : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; + + function respond(o) { + var status = xhr.status, result; + if (!status && hasResponse(xhr) + || status >= 200 && status < 300 + || status === 304) { + if (response) { + try { + result = response.call(request, xhr); + } catch (e) { + event.call("error", request, e); + return; + } + } else { + result = xhr; + } + event.call("load", request, result); + } else { + event.call("error", request, o); + } + } + + xhr.onprogress = function(e) { + event.call("progress", request, e); + }; + + request = { + header: function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers.get(name); + if (value == null) headers.remove(name); + else headers.set(name, value + ""); + return request; + }, + + // If mimeType is non-null and no Accept header is set, a default is used. + mimeType: function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return request; + }, + + // Specifies what type the response value should take; + // for instance, arraybuffer, blob, document, or text. + responseType: function(value) { + if (!arguments.length) return responseType; + responseType = value; + return request; + }, + + timeout: function(value) { + if (!arguments.length) return timeout; + timeout = +value; + return request; + }, + + user: function(value) { + return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); + }, + + password: function(value) { + return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); + }, + + // Specify how to convert the response content to a specific type; + // changes the callback value on "load" events. + response: function(value) { + response = value; + return request; + }, + + // Alias for send("GET", …). + get: function(data, callback) { + return request.send("GET", data, callback); + }, + + // Alias for send("POST", …). + post: function(data, callback) { + return request.send("POST", data, callback); + }, + + // If callback is non-null, it will be used for error and load events. + send: function(method, data, callback) { + xhr.open(method, url, true, user, password); + if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); + if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); + if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); + if (responseType != null) xhr.responseType = responseType; + if (timeout > 0) xhr.timeout = timeout; + if (callback == null && typeof data === "function") callback = data, data = null; + if (callback != null && callback.length === 1) callback = fixCallback(callback); + if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); + event.call("beforesend", request, xhr); + xhr.send(data == null ? null : data); + return request; + }, + + abort: function() { + xhr.abort(); + return request; + }, + + on: function() { + var value = event.on.apply(event, arguments); + return value === event ? request : value; + } + }; + + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return request.get(callback); + } + + return request; +}; + +function fixCallback(callback) { + return function(error, xhr) { + callback(error == null ? xhr : null); + }; +} + +function hasResponse(xhr) { + var type = xhr.responseType; + return type && type !== "text" + ? xhr.response // null on error + : xhr.responseText; // "" on error +} + +var type$1 = function(defaultMimeType, response) { + return function(url, callback) { + var r = request(url).mimeType(defaultMimeType).response(response); + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return r.get(callback); + } + return r; + }; +}; + +var html = type$1("text/html", function(xhr) { + return document.createRange().createContextualFragment(xhr.responseText); +}); + +var json = type$1("application/json", function(xhr) { + return JSON.parse(xhr.responseText); +}); + +var text = type$1("text/plain", function(xhr) { + return xhr.responseText; +}); + +var xml = type$1("application/xml", function(xhr) { + var xml = xhr.responseXML; + if (!xml) throw new Error("parse error"); + return xml; +}); + +var dsv$1 = function(defaultMimeType, parse) { + return function(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var r = request(url).mimeType(defaultMimeType); + r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; + r.row(row); + return callback ? r.get(callback) : r; + }; +}; + +function responseOf(parse, row) { + return function(request$$1) { + return parse(request$$1.responseText, row); + }; +} + +var csv$1 = dsv$1("text/csv", csvParse); + +var tsv$1 = dsv$1("text/tab-separated-values", tsvParse); + +var array$2 = Array.prototype; + +var map$3 = array$2.map; +var slice$4 = array$2.slice; + +var implicit = {name: "implicit"}; + +function ordinal(range) { + var index = map$1(), + domain = [], + unknown = implicit; + + range = range == null ? [] : slice$4.call(range); + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) return unknown; + index.set(key, i = domain.push(d)); + } + return range[(i - 1) % range.length]; + } + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = map$1(); + var i = -1, n = _.length, d, key; + while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); + return scale; + }; + + scale.range = function(_) { + return arguments.length ? (range = slice$4.call(_), scale) : range.slice(); + }; + + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function() { + return ordinal() + .domain(domain) + .range(range) + .unknown(unknown); + }; + + return scale; +} + +function band() { + var scale = ordinal().unknown(undefined), + domain = scale.domain, + ordinalRange = scale.range, + range$$1 = [0, 1], + step, + bandwidth, + round = false, + paddingInner = 0, + paddingOuter = 0, + align = 0.5; + + delete scale.unknown; + + function rescale() { + var n = domain().length, + reverse = range$$1[1] < range$$1[0], + start = range$$1[reverse - 0], + stop = range$$1[1 - reverse]; + step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); + if (round) step = Math.floor(step); + start += (stop - start - step * (n - paddingInner)) * align; + bandwidth = step * (1 - paddingInner); + if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); + var values = sequence(n).map(function(i) { return start + step * i; }); + return ordinalRange(reverse ? values.reverse() : values); + } + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = [+_[0], +_[1]], round = true, rescale(); + }; + + scale.bandwidth = function() { + return bandwidth; + }; + + scale.step = function() { + return step; + }; + + scale.round = function(_) { + return arguments.length ? (round = !!_, rescale()) : round; + }; + + scale.padding = function(_) { + return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingInner = function(_) { + return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingOuter = function(_) { + return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; + }; + + scale.align = function(_) { + return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; + }; + + scale.copy = function() { + return band() + .domain(domain()) + .range(range$$1) + .round(round) + .paddingInner(paddingInner) + .paddingOuter(paddingOuter) + .align(align); + }; + + return rescale(); +} + +function pointish(scale) { + var copy = scale.copy; + + scale.padding = scale.paddingOuter; + delete scale.paddingInner; + delete scale.paddingOuter; + + scale.copy = function() { + return pointish(copy()); + }; + + return scale; +} + +function point$1() { + return pointish(band().paddingInner(1)); +} + +var constant$9 = function(x) { + return function() { + return x; + }; +}; + +var number$1 = function(x) { + return +x; +}; + +var unit = [0, 1]; + +function deinterpolateLinear(a, b) { + return (b -= (a = +a)) + ? function(x) { return (x - a) / b; } + : constant$9(b); +} + +function deinterpolateClamp(deinterpolate) { + return function(a, b) { + var d = deinterpolate(a = +a, b = +b); + return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; + }; +} + +function reinterpolateClamp(reinterpolate) { + return function(a, b) { + var r = reinterpolate(a = +a, b = +b); + return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; + }; +} + +function bimap(domain, range$$1, deinterpolate, reinterpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; + if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); + else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); + return function(x) { return r0(d0(x)); }; +} + +function polymap(domain, range$$1, deinterpolate, reinterpolate) { + var j = Math.min(domain.length, range$$1.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range$$1 = range$$1.slice().reverse(); + } + + while (++i < j) { + d[i] = deinterpolate(domain[i], domain[i + 1]); + r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); + } + + return function(x) { + var i = bisectRight(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; +} + +function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()); +} + +// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. +function continuous(deinterpolate, reinterpolate) { + var domain = unit, + range$$1 = unit, + interpolate$$1 = interpolateValue, + clamp = false, + piecewise, + output, + input; + + function rescale() { + piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } + + function scale(x) { + return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); + } + + scale.invert = function(y) { + return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); + }; + + scale.domain = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = slice$4.call(_), interpolate$$1 = interpolateRound, rescale(); + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, rescale()) : clamp; + }; + + scale.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; + }; + + return rescale(); +} + +var tickFormat = function(domain, count, specifier) { + var start = domain[0], + stop = domain[domain.length - 1], + step = tickStep(start, stop, count == null ? 10 : count), + precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; + return exports.formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return exports.format(specifier); +}; + +function linearish(scale) { + var domain = scale.domain; + + scale.ticks = function(count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + + scale.tickFormat = function(count, specifier) { + return tickFormat(domain(), count, specifier); + }; + + scale.nice = function(count) { + if (count == null) count = 10; + + var d = domain(), + i0 = 0, + i1 = d.length - 1, + start = d[i0], + stop = d[i1], + step; + + if (stop < start) { + step = start, start = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + + step = tickIncrement(start, stop, count); + + if (step > 0) { + start = Math.floor(start / step) * step; + stop = Math.ceil(stop / step) * step; + step = tickIncrement(start, stop, count); + } else if (step < 0) { + start = Math.ceil(start * step) / step; + stop = Math.floor(stop * step) / step; + step = tickIncrement(start, stop, count); + } + + if (step > 0) { + d[i0] = Math.floor(start / step) * step; + d[i1] = Math.ceil(stop / step) * step; + domain(d); + } else if (step < 0) { + d[i0] = Math.ceil(start * step) / step; + d[i1] = Math.floor(stop * step) / step; + domain(d); + } + + return scale; + }; + + return scale; +} + +function linear$2() { + var scale = continuous(deinterpolateLinear, reinterpolate); + + scale.copy = function() { + return copy(scale, linear$2()); + }; + + return linearish(scale); +} + +function identity$6() { + var domain = [0, 1]; + + function scale(x) { + return +x; + } + + scale.invert = scale; + + scale.domain = scale.range = function(_) { + return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice(); + }; + + scale.copy = function() { + return identity$6().domain(domain); + }; + + return linearish(scale); +} + +var nice = function(domain, interval) { + domain = domain.slice(); + + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; + + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } + + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; +}; + +function deinterpolate(a, b) { + return (b = Math.log(b / a)) + ? function(x) { return Math.log(x / a) / b; } + : constant$9(b); +} + +function reinterpolate$1(a, b) { + return a < 0 + ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } + : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; +} + +function pow10(x) { + return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; +} + +function powp(base) { + return base === 10 ? pow10 + : base === Math.E ? Math.exp + : function(x) { return Math.pow(base, x); }; +} + +function logp(base) { + return base === Math.E ? Math.log + : base === 10 && Math.log10 + || base === 2 && Math.log2 + || (base = Math.log(base), function(x) { return Math.log(x) / base; }); +} + +function reflect(f) { + return function(x) { + return -f(-x); + }; +} + +function log$1() { + var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]), + domain = scale.domain, + base = 10, + logs = logp(10), + pows = powp(10); + + function rescale() { + logs = logp(base), pows = powp(base); + if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); + return scale; + } + + scale.base = function(_) { + return arguments.length ? (base = +_, rescale()) : base; + }; + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.ticks = function(count) { + var d = domain(), + u = d[0], + v = d[d.length - 1], + r; + + if (r = v < u) i = u, u = v, v = i; + + var i = logs(u), + j = logs(v), + p, + k, + t, + n = count == null ? 10 : +count, + z = []; + + if (!(base % 1) && j - i < n) { + i = Math.round(i) - 1, j = Math.round(j) + 1; + if (u > 0) for (; i < j; ++i) { + for (k = 1, p = pows(i); k < base; ++k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } else for (; i < j; ++i) { + for (k = base - 1, p = pows(i); k >= 1; --k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } + } else { + z = ticks(i, j, Math.min(j - i, n)).map(pows); + } + + return r ? z.reverse() : z; + }; + + scale.tickFormat = function(count, specifier) { + if (specifier == null) specifier = base === 10 ? ".0e" : ","; + if (typeof specifier !== "function") specifier = exports.format(specifier); + if (count === Infinity) return specifier; + if (count == null) count = 10; + var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? + return function(d) { + var i = d / pows(Math.round(logs(d))); + if (i * base < base - 0.5) i *= base; + return i <= k ? specifier(d) : ""; + }; + }; + + scale.nice = function() { + return domain(nice(domain(), { + floor: function(x) { return pows(Math.floor(logs(x))); }, + ceil: function(x) { return pows(Math.ceil(logs(x))); } + })); + }; + + scale.copy = function() { + return copy(scale, log$1().base(base)); + }; + + return scale; +} + +function raise$1(x, exponent) { + return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); +} + +function pow$1() { + var exponent = 1, + scale = continuous(deinterpolate, reinterpolate), + domain = scale.domain; + + function deinterpolate(a, b) { + return (b = raise$1(b, exponent) - (a = raise$1(a, exponent))) + ? function(x) { return (raise$1(x, exponent) - a) / b; } + : constant$9(b); + } + + function reinterpolate(a, b) { + b = raise$1(b, exponent) - (a = raise$1(a, exponent)); + return function(t) { return raise$1(a + b * t, 1 / exponent); }; + } + + scale.exponent = function(_) { + return arguments.length ? (exponent = +_, domain(domain())) : exponent; + }; + + scale.copy = function() { + return copy(scale, pow$1().exponent(exponent)); + }; + + return linearish(scale); +} + +function sqrt$1() { + return pow$1().exponent(0.5); +} + +function quantile$$1() { + var domain = [], + range$$1 = [], + thresholds = []; + + function rescale() { + var i = 0, n = Math.max(1, range$$1.length); + thresholds = new Array(n - 1); + while (++i < n) thresholds[i - 1] = threshold(domain, i / n); + return scale; + } + + function scale(x) { + if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)]; + } + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] : [ + i > 0 ? thresholds[i - 1] : domain[0], + i < thresholds.length ? thresholds[i] : domain[domain.length - 1] + ]; + }; + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); + domain.sort(ascending); + return rescale(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), rescale()) : range$$1.slice(); + }; + + scale.quantiles = function() { + return thresholds.slice(); + }; + + scale.copy = function() { + return quantile$$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +function quantize$1() { + var x0 = 0, + x1 = 1, + n = 1, + domain = [0.5], + range$$1 = [0, 1]; + + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; + } + + function rescale() { + var i = -1; + domain = new Array(n); + while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); + return scale; + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; + }; + + scale.range = function(_) { + return arguments.length ? (n = (range$$1 = slice$4.call(_)).length - 1, rescale()) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] + : i < 1 ? [x0, domain[0]] + : i >= n ? [domain[n - 1], x1] + : [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return quantize$1() + .domain([x0, x1]) + .range(range$$1); + }; + + return linearish(scale); +} + +function threshold$1() { + var domain = [0.5], + range$$1 = [0, 1], + n = 1; + + function scale(x) { + if (x <= x) return range$$1[bisectRight(domain, x, 0, n)]; + } + + scale.domain = function(_) { + return arguments.length ? (domain = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice$4.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return threshold$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +var t0$1 = new Date; +var t1$1 = new Date; + +function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; + } + + interval.floor = interval; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; + }; + + interval.round = function(date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function(start, stop, step) { + var range = []; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty + }); + }; + + if (count) { + interval.count = function(start, end) { + t0$1.setTime(+start), t1$1.setTime(+end); + floori(t0$1), floori(t1$1); + return Math.floor(count(t0$1, t1$1)); + }; + + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; + } + + return interval; +} + +var millisecond = newInterval(function() { + // noop +}, function(date, step) { + date.setTime(+date + step); +}, function(start, end) { + return end - start; +}); + +// An optimized implementation for this simple case. +millisecond.every = function(k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) return null; + if (!(k > 1)) return millisecond; + return newInterval(function(date) { + date.setTime(Math.floor(date / k) * k); + }, function(date, step) { + date.setTime(+date + step * k); + }, function(start, end) { + return (end - start) / k; + }); +}; + +var milliseconds = millisecond.range; + +var durationSecond$1 = 1e3; +var durationMinute$1 = 6e4; +var durationHour$1 = 36e5; +var durationDay$1 = 864e5; +var durationWeek$1 = 6048e5; + +var second = newInterval(function(date) { + date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1); +}, function(date, step) { + date.setTime(+date + step * durationSecond$1); +}, function(start, end) { + return (end - start) / durationSecond$1; +}, function(date) { + return date.getUTCSeconds(); +}); + +var seconds = second.range; + +var minute = newInterval(function(date) { + date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1); +}, function(date, step) { + date.setTime(+date + step * durationMinute$1); +}, function(start, end) { + return (end - start) / durationMinute$1; +}, function(date) { + return date.getMinutes(); +}); + +var minutes = minute.range; + +var hour = newInterval(function(date) { + var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1; + if (offset < 0) offset += durationHour$1; + date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset); +}, function(date, step) { + date.setTime(+date + step * durationHour$1); +}, function(start, end) { + return (end - start) / durationHour$1; +}, function(date) { + return date.getHours(); +}); + +var hours = hour.range; + +var day = newInterval(function(date) { + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setDate(date.getDate() + step); +}, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1; +}, function(date) { + return date.getDate() - 1; +}); + +var days = day.range; + +function weekday(i) { + return newInterval(function(date) { + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setDate(date.getDate() + step * 7); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1; + }); +} + +var sunday = weekday(0); +var monday = weekday(1); +var tuesday = weekday(2); +var wednesday = weekday(3); +var thursday = weekday(4); +var friday = weekday(5); +var saturday = weekday(6); + +var sundays = sunday.range; +var mondays = monday.range; +var tuesdays = tuesday.range; +var wednesdays = wednesday.range; +var thursdays = thursday.range; +var fridays = friday.range; +var saturdays = saturday.range; + +var month = newInterval(function(date) { + date.setDate(1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setMonth(date.getMonth() + step); +}, function(start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; +}, function(date) { + return date.getMonth(); +}); + +var months = month.range; + +var year = newInterval(function(date) { + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setFullYear(date.getFullYear() + step); +}, function(start, end) { + return end.getFullYear() - start.getFullYear(); +}, function(date) { + return date.getFullYear(); +}); + +// An optimized implementation for this simple case. +year.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setFullYear(Math.floor(date.getFullYear() / k) * k); + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setFullYear(date.getFullYear() + step * k); + }); +}; + +var years = year.range; + +var utcMinute = newInterval(function(date) { + date.setUTCSeconds(0, 0); +}, function(date, step) { + date.setTime(+date + step * durationMinute$1); +}, function(start, end) { + return (end - start) / durationMinute$1; +}, function(date) { + return date.getUTCMinutes(); +}); + +var utcMinutes = utcMinute.range; + +var utcHour = newInterval(function(date) { + date.setUTCMinutes(0, 0, 0); +}, function(date, step) { + date.setTime(+date + step * durationHour$1); +}, function(start, end) { + return (end - start) / durationHour$1; +}, function(date) { + return date.getUTCHours(); +}); + +var utcHours = utcHour.range; + +var utcDay = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCDate(date.getUTCDate() + step); +}, function(start, end) { + return (end - start) / durationDay$1; +}, function(date) { + return date.getUTCDate() - 1; +}); + +var utcDays = utcDay.range; + +function utcWeekday(i) { + return newInterval(function(date) { + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function(start, end) { + return (end - start) / durationWeek$1; + }); +} + +var utcSunday = utcWeekday(0); +var utcMonday = utcWeekday(1); +var utcTuesday = utcWeekday(2); +var utcWednesday = utcWeekday(3); +var utcThursday = utcWeekday(4); +var utcFriday = utcWeekday(5); +var utcSaturday = utcWeekday(6); + +var utcSundays = utcSunday.range; +var utcMondays = utcMonday.range; +var utcTuesdays = utcTuesday.range; +var utcWednesdays = utcWednesday.range; +var utcThursdays = utcThursday.range; +var utcFridays = utcFriday.range; +var utcSaturdays = utcSaturday.range; + +var utcMonth = newInterval(function(date) { + date.setUTCDate(1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCMonth(date.getUTCMonth() + step); +}, function(start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; +}, function(date) { + return date.getUTCMonth(); +}); + +var utcMonths = utcMonth.range; + +var utcYear = newInterval(function(date) { + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); +}, function(start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); +}, function(date) { + return date.getUTCFullYear(); +}); + +// An optimized implementation for this simple case. +utcYear.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step * k); + }); +}; + +var utcYears = utcYear.range; + +function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); +} + +function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); +} + +function newYear(y) { + return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +} + +function formatLocale$1(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; + + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); + + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "S": formatSeconds, + "U": formatWeekNumberSunday, + "w": formatWeekdayNumber, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; + + var utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "S": formatUTCSeconds, + "U": formatUTCWeekNumberSunday, + "w": formatUTCWeekdayNumber, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; + + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "S": parseSeconds, + "U": parseWeekNumberSunday, + "w": parseWeekdayNumber, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; + + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); + + function newFormat(specifier, formats) { + return function(date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; + + if (!(date instanceof Date)) date = new Date(+date); + + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); + else pad = c === "e" ? " " : "0"; + if (format = formats[c]) c = format(date, pad); + string.push(c); + j = i + 1; + } + } + + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } + + function newParse(specifier, newDate) { + return function(string) { + var d = newYear(1900), + i = parseSpecifier(d, specifier, string += "", 0); + if (i != string.length) return null; + + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) d.H = d.H % 12 + d.p * 12; + + // Convert day-of-week and week-of-year to day-of-year. + if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; + } + + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } + + // Otherwise, all fields are in local time. + return newDate(d); + }; + } + + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; + + while (i < n) { + if (j >= m) return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + + return j; + } + + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } + + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); + } + + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } + + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } + + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } + + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } + + function formatMonth(d) { + return locale_months[d.getMonth()]; + } + + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } + + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } + + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; + } + + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; + } + + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; + } + + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + return { + format: function(specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function() { return specifier; }; + return f; + }, + parse: function(specifier) { + var p = newParse(specifier += "", localDate); + p.toString = function() { return specifier; }; + return p; + }, + utcFormat: function(specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function() { return specifier; }; + return f; + }, + utcParse: function(specifier) { + var p = newParse(specifier, utcDate); + p.toString = function() { return specifier; }; + return p; + } + }; +} + +var pads = {"-": "", "_": " ", "0": "0"}; +var numberRe = /^\s*\d+/; +var percentRe = /^%/; +var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + +function pad(value, fill, width) { + var sign = value < 0 ? "-" : "", + string = (sign ? -value : value) + "", + length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); +} + +function requote(s) { + return s.replace(requoteRe, "\\$&"); +} + +function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +} + +function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) map[names[i].toLowerCase()] = i; + return map; +} + +function parseWeekdayNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.U = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.W = +n[0], i + n[0].length) : -1; +} + +function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; +} + +function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; +} + +function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; +} + +function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; +} + +function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; +} + +function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; +} + +function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; +} + +function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; +} + +function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; +} + +function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; +} + +function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; +} + +function formatDayOfMonth(d, p) { + return pad(d.getDate(), p, 2); +} + +function formatHour24(d, p) { + return pad(d.getHours(), p, 2); +} + +function formatHour12(d, p) { + return pad(d.getHours() % 12 || 12, p, 2); +} + +function formatDayOfYear(d, p) { + return pad(1 + day.count(year(d), d), p, 3); +} + +function formatMilliseconds(d, p) { + return pad(d.getMilliseconds(), p, 3); +} + +function formatMonthNumber(d, p) { + return pad(d.getMonth() + 1, p, 2); +} + +function formatMinutes(d, p) { + return pad(d.getMinutes(), p, 2); +} + +function formatSeconds(d, p) { + return pad(d.getSeconds(), p, 2); +} + +function formatWeekNumberSunday(d, p) { + return pad(sunday.count(year(d), d), p, 2); +} + +function formatWeekdayNumber(d) { + return d.getDay(); +} + +function formatWeekNumberMonday(d, p) { + return pad(monday.count(year(d), d), p, 2); +} + +function formatYear(d, p) { + return pad(d.getFullYear() % 100, p, 2); +} + +function formatFullYear(d, p) { + return pad(d.getFullYear() % 10000, p, 4); +} + +function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad(z / 60 | 0, "0", 2) + + pad(z % 60, "0", 2); +} + +function formatUTCDayOfMonth(d, p) { + return pad(d.getUTCDate(), p, 2); +} + +function formatUTCHour24(d, p) { + return pad(d.getUTCHours(), p, 2); +} + +function formatUTCHour12(d, p) { + return pad(d.getUTCHours() % 12 || 12, p, 2); +} + +function formatUTCDayOfYear(d, p) { + return pad(1 + utcDay.count(utcYear(d), d), p, 3); +} + +function formatUTCMilliseconds(d, p) { + return pad(d.getUTCMilliseconds(), p, 3); +} + +function formatUTCMonthNumber(d, p) { + return pad(d.getUTCMonth() + 1, p, 2); +} + +function formatUTCMinutes(d, p) { + return pad(d.getUTCMinutes(), p, 2); +} + +function formatUTCSeconds(d, p) { + return pad(d.getUTCSeconds(), p, 2); +} + +function formatUTCWeekNumberSunday(d, p) { + return pad(utcSunday.count(utcYear(d), d), p, 2); +} + +function formatUTCWeekdayNumber(d) { + return d.getUTCDay(); +} + +function formatUTCWeekNumberMonday(d, p) { + return pad(utcMonday.count(utcYear(d), d), p, 2); +} + +function formatUTCYear(d, p) { + return pad(d.getUTCFullYear() % 100, p, 2); +} + +function formatUTCFullYear(d, p) { + return pad(d.getUTCFullYear() % 10000, p, 4); +} + +function formatUTCZone() { + return "+0000"; +} + +function formatLiteralPercent() { + return "%"; +} + +var locale$2; + + + + + +defaultLocale$1({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + periods: ["AM", "PM"], + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +}); + +function defaultLocale$1(definition) { + locale$2 = formatLocale$1(definition); + exports.timeFormat = locale$2.format; + exports.timeParse = locale$2.parse; + exports.utcFormat = locale$2.utcFormat; + exports.utcParse = locale$2.utcParse; + return locale$2; +} + +var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + +function formatIsoNative(date) { + return date.toISOString(); +} + +var formatIso = Date.prototype.toISOString + ? formatIsoNative + : exports.utcFormat(isoSpecifier); + +function parseIsoNative(string) { + var date = new Date(string); + return isNaN(date) ? null : date; +} + +var parseIso = +new Date("2000-01-01T00:00:00.000Z") + ? parseIsoNative + : exports.utcParse(isoSpecifier); + +var durationSecond = 1000; +var durationMinute = durationSecond * 60; +var durationHour = durationMinute * 60; +var durationDay = durationHour * 24; +var durationWeek = durationDay * 7; +var durationMonth = durationDay * 30; +var durationYear = durationDay * 365; + +function date$1(t) { + return new Date(t); +} + +function number$2(t) { + return t instanceof Date ? +t : +new Date(+t); +} + +function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) { + var scale = continuous(deinterpolateLinear, reinterpolate), + invert = scale.invert, + domain = scale.domain; + + var formatMillisecond = format(".%L"), + formatSecond = format(":%S"), + formatMinute = format("%I:%M"), + formatHour = format("%I %p"), + formatDay = format("%a %d"), + formatWeek = format("%b %d"), + formatMonth = format("%B"), + formatYear = format("%Y"); + + var tickIntervals = [ + [second$$1, 1, durationSecond], + [second$$1, 5, 5 * durationSecond], + [second$$1, 15, 15 * durationSecond], + [second$$1, 30, 30 * durationSecond], + [minute$$1, 1, durationMinute], + [minute$$1, 5, 5 * durationMinute], + [minute$$1, 15, 15 * durationMinute], + [minute$$1, 30, 30 * durationMinute], + [ hour$$1, 1, durationHour ], + [ hour$$1, 3, 3 * durationHour ], + [ hour$$1, 6, 6 * durationHour ], + [ hour$$1, 12, 12 * durationHour ], + [ day$$1, 1, durationDay ], + [ day$$1, 2, 2 * durationDay ], + [ week, 1, durationWeek ], + [ month$$1, 1, durationMonth ], + [ month$$1, 3, 3 * durationMonth ], + [ year$$1, 1, durationYear ] + ]; + + function tickFormat(date) { + return (second$$1(date) < date ? formatMillisecond + : minute$$1(date) < date ? formatSecond + : hour$$1(date) < date ? formatMinute + : day$$1(date) < date ? formatHour + : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year$$1(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = tickStep(start / durationYear, stop / durationYear, interval); + interval = year$$1; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = tickStep(start, stop, interval); + interval = millisecond$$1; + } + } + + return step == null ? interval : interval.every(step); + } + + scale.invert = function(y) { + return new Date(invert(y)); + }; + + scale.domain = function(_) { + return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1); + }; + + scale.ticks = function(interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; + }; + + scale.tickFormat = function(count, specifier) { + return specifier == null ? tickFormat : format(specifier); + }; + + scale.nice = function(interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(nice(d, interval)) + : scale; + }; + + scale.copy = function() { + return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format)); + }; + + return scale; +} + +var time = function() { + return calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); +}; + +var utcTime = function() { + return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); +}; + +var colors = function(s) { + return s.match(/.{6}/g).map(function(x) { + return "#" + x; + }); +}; + +var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); + +var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); + +var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); + +var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); + +var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); + +var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + +var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + +var rainbow = cubehelix(); + +var rainbow$1 = function(t) { + if (t < 0 || t > 1) t -= Math.floor(t); + var ts = Math.abs(t - 0.5); + rainbow.h = 360 * t - 100; + rainbow.s = 1.5 - 1.5 * ts; + rainbow.l = 0.8 - 0.9 * ts; + return rainbow + ""; +}; + +function ramp(range) { + var n = range.length; + return function(t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; +} + +var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); + +var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); + +var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); + +var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); + +function sequential(interpolator) { + var x0 = 0, + x1 = 1, + clamp = false; + + function scale(x) { + var t = (x - x0) / (x1 - x0); + return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; + + scale.interpolator = function(_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.copy = function() { + return sequential(interpolator).domain([x0, x1]).clamp(clamp); + }; + + return linearish(scale); +} + +var constant$10 = function(x) { + return function constant() { + return x; + }; +}; + +var abs$1 = Math.abs; +var atan2$1 = Math.atan2; +var cos$2 = Math.cos; +var max$2 = Math.max; +var min$1 = Math.min; +var sin$2 = Math.sin; +var sqrt$2 = Math.sqrt; + +var epsilon$3 = 1e-12; +var pi$4 = Math.PI; +var halfPi$3 = pi$4 / 2; +var tau$4 = 2 * pi$4; + +function acos$1(x) { + return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x); +} + +function asin$1(x) { + return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x); +} + +function arcInnerRadius(d) { + return d.innerRadius; +} + +function arcOuterRadius(d) { + return d.outerRadius; +} + +function arcStartAngle(d) { + return d.startAngle; +} + +function arcEndAngle(d) { + return d.endAngle; +} + +function arcPadAngle(d) { + return d && d.padAngle; // Note: optional! +} + +function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0, y10 = y1 - y0, + x32 = x3 - x2, y32 = y3 - y2, + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); + return [x0 + t * x10, y0 + t * y10]; +} + +// Compute perpendicular offset line of length rc. +// http://mathworld.wolfram.com/Circle-LineIntersection.html +function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { + var x01 = x0 - x1, + y01 = y0 - y1, + lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01), + ox = lo * y01, + oy = -lo * x01, + x11 = x0 + ox, + y11 = y0 + oy, + x10 = x1 + ox, + y10 = y1 + oy, + x00 = (x11 + x10) / 2, + y00 = (y11 + y10) / 2, + dx = x10 - x11, + dy = y10 - y11, + d2 = dx * dx + dy * dy, + r = r1 - rc, + D = x11 * y10 - x10 * y11, + d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)), + cx0 = (D * dy - dx * d) / d2, + cy0 = (-D * dx - dy * d) / d2, + cx1 = (D * dy + dx * d) / d2, + cy1 = (-D * dx + dy * d) / d2, + dx0 = cx0 - x00, + dy0 = cy0 - y00, + dx1 = cx1 - x00, + dy1 = cy1 - y00; + + // Pick the closer of the two intersection points. + // TODO Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (r1 / r - 1), + y11: cy0 * (r1 / r - 1) + }; +} + +var arc = function() { + var innerRadius = arcInnerRadius, + outerRadius = arcOuterRadius, + cornerRadius = constant$10(0), + padRadius = null, + startAngle = arcStartAngle, + endAngle = arcEndAngle, + padAngle = arcPadAngle, + context = null; + + function arc() { + var buffer, + r, + r0 = +innerRadius.apply(this, arguments), + r1 = +outerRadius.apply(this, arguments), + a0 = startAngle.apply(this, arguments) - halfPi$3, + a1 = endAngle.apply(this, arguments) - halfPi$3, + da = abs$1(a1 - a0), + cw = a1 > a0; + + if (!context) context = buffer = path(); + + // Ensure that the outer radius is always larger than the inner radius. + if (r1 < r0) r = r1, r1 = r0, r0 = r; + + // Is it a point? + if (!(r1 > epsilon$3)) context.moveTo(0, 0); + + // Or is it a circle or annulus? + else if (da > tau$4 - epsilon$3) { + context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0)); + context.arc(0, 0, r1, a0, a1, !cw); + if (r0 > epsilon$3) { + context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1)); + context.arc(0, 0, r0, a1, a0, cw); + } + } + + // Or is it a circular or annular sector? + else { + var a01 = a0, + a11 = a1, + a00 = a0, + a10 = a1, + da0 = da, + da1 = da, + ap = padAngle.apply(this, arguments) / 2, + rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)), + rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), + rc0 = rc, + rc1 = rc, + t0, + t1; + + // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. + if (rp > epsilon$3) { + var p0 = asin$1(rp / r0 * sin$2(ap)), + p1 = asin$1(rp / r1 * sin$2(ap)); + if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; + else da0 = 0, a00 = a10 = (a0 + a1) / 2; + if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; + else da1 = 0, a01 = a11 = (a0 + a1) / 2; + } + + var x01 = r1 * cos$2(a01), + y01 = r1 * sin$2(a01), + x10 = r0 * cos$2(a10), + y10 = r0 * sin$2(a10); + + // Apply rounded corners? + if (rc > epsilon$3) { + var x11 = r1 * cos$2(a11), + y11 = r1 * sin$2(a11), + x00 = r0 * cos$2(a00), + y00 = r0 * sin$2(a00); + + // Restrict the corner radius according to the sector angle. + if (da < pi$4) { + var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], + ax = x01 - oc[0], + ay = y01 - oc[1], + bx = x11 - oc[0], + by = y11 - oc[1], + kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2), + lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = min$1(rc, (r0 - lc) / (kc - 1)); + rc1 = min$1(rc, (r1 - lc) / (kc + 1)); + } + } + + // Is the sector collapsed to a line? + if (!(da1 > epsilon$3)) context.moveTo(x01, y01); + + // Does the sector’s outer ring have rounded corners? + else if (rc1 > epsilon$3) { + t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); + t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); + + context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); + context.arc(0, 0, r1, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), !cw); + context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); + } + } + + // Or is the outer ring just a circular arc? + else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); + + // Is there no inner ring, and it’s a circular sector? + // Or perhaps it’s an annular sector collapsed due to padding? + if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10); + + // Does the sector’s inner ring (or point) have rounded corners? + else if (rc0 > epsilon$3) { + t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); + t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); + + context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); + context.arc(0, 0, r0, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), cw); + context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); + } + } + + // Or is the inner ring just a circular arc? + else context.arc(0, 0, r0, a10, a00, cw); + } + + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, + a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2; + return [cos$2(a) * r, sin$2(a) * r]; + }; + + arc.innerRadius = function(_) { + return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius; + }; + + arc.outerRadius = function(_) { + return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius; + }; + + arc.cornerRadius = function(_) { + return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius; + }; + + arc.padRadius = function(_) { + return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius; + }; + + arc.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle; + }; + + arc.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle; + }; + + arc.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle; + }; + + arc.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), arc) : context; + }; + + return arc; +}; + +function Linear(context) { + this._context = context; +} + +Linear.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: this._context.lineTo(x, y); break; + } + } +}; + +var curveLinear = function(context) { + return new Linear(context); +}; + +function x$3(p) { + return p[0]; +} + +function y$3(p) { + return p[1]; +} + +var line = function() { + var x$$1 = x$3, + y$$1 = y$3, + defined = constant$10(true), + context = null, + curve = curveLinear, + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) output.lineStart(); + else output.lineEnd(); + } + if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); + } + + if (buffer) return output = null, buffer + "" || null; + } + + line.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1; + }; + + line.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1; + }; + + line.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined; + }; + + line.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; +}; + +var area$2 = function() { + var x0 = x$3, + x1 = null, + y0 = constant$10(0), + y1 = y$3, + defined = constant$10(true), + context = null, + curve = curveLinear, + output = null; + + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); + + if (context == null) output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } + + if (buffer) return output = null, buffer + "" || null; + } + + function arealine() { + return line().defined(defined).curve(curve).context(context); + } + + area.x = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0; + }; + + area.x0 = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0; + }; + + area.x1 = function(_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1; + }; + + area.y = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0; + }; + + area.y0 = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0; + }; + + area.y1 = function(_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1; + }; + + area.lineX0 = + area.lineY0 = function() { + return arealine().x(x0).y(y0); + }; + + area.lineY1 = function() { + return arealine().x(x0).y(y1); + }; + + area.lineX1 = function() { + return arealine().x(x1).y(y0); + }; + + area.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined; + }; + + area.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; + + area.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; + }; + + return area; +}; + +var descending$1 = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var identity$7 = function(d) { + return d; +}; + +var pie = function() { + var value = identity$7, + sortValues = descending$1, + sort = null, + startAngle = constant$10(0), + endAngle = constant$10(tau$4), + padAngle = constant$10(0); + + function pie(data) { + var i, + n = data.length, + j, + k, + sum = 0, + index = new Array(n), + arcs = new Array(n), + a0 = +startAngle.apply(this, arguments), + da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)), + a1, + p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), + pa = p * (da < 0 ? -1 : 1), + v; + + for (i = 0; i < n; ++i) { + if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { + sum += v; + } + } + + // Optionally sort the arcs by previously-computed values or by data. + if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); + else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); + + // Compute the arcs! They are stored in the original data's order. + for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { + j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { + data: data[j], + index: i, + value: v, + startAngle: a0, + endAngle: a1, + padAngle: p + }; + } + + return arcs; + } + + pie.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value; + }; + + pie.sortValues = function(_) { + return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; + }; + + pie.sort = function(_) { + return arguments.length ? (sort = _, sortValues = null, pie) : sort; + }; + + pie.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle; + }; + + pie.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle; + }; + + pie.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle; + }; + + return pie; +}; + +var curveRadialLinear = curveRadial(curveLinear); + +function Radial(curve) { + this._curve = curve; +} + +Radial.prototype = { + areaStart: function() { + this._curve.areaStart(); + }, + areaEnd: function() { + this._curve.areaEnd(); + }, + lineStart: function() { + this._curve.lineStart(); + }, + lineEnd: function() { + this._curve.lineEnd(); + }, + point: function(a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); + } +}; + +function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); + } + + radial._curve = curve; + + return radial; +} + +function radialLine(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return l; +} + +var radialLine$1 = function() { + return radialLine(line().curve(curveRadialLinear)); +}; + +var radialArea = function() { + var a = area$2().curve(curveRadialLinear), + c = a.curve, + x0 = a.lineX0, + x1 = a.lineX1, + y0 = a.lineY0, + y1 = a.lineY1; + + a.angle = a.x, delete a.x; + a.startAngle = a.x0, delete a.x0; + a.endAngle = a.x1, delete a.x1; + a.radius = a.y, delete a.y; + a.innerRadius = a.y0, delete a.y0; + a.outerRadius = a.y1, delete a.y1; + a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0; + a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1; + a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0; + a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1; + + a.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return a; +}; + +var slice$5 = Array.prototype.slice; + +var radialPoint = function(x, y) { + return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; +}; + +function linkSource(d) { + return d.source; +} + +function linkTarget(d) { + return d.target; +} + +function link$2(curve) { + var source = linkSource, + target = linkTarget, + x$$1 = x$3, + y$$1 = y$3, + context = null; + + function link() { + var buffer, argv = slice$5.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); + if (!context) context = buffer = path(); + curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); + if (buffer) return context = null, buffer + "" || null; + } + + link.source = function(_) { + return arguments.length ? (source = _, link) : source; + }; + + link.target = function(_) { + return arguments.length ? (target = _, link) : target; + }; + + link.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), link) : x$$1; + }; + + link.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), link) : y$$1; + }; + + link.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), link) : context; + }; + + return link; +} + +function curveHorizontal(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); +} + +function curveVertical(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); +} + +function curveRadial$1(context, x0, y0, x1, y1) { + var p0 = radialPoint(x0, y0), + p1 = radialPoint(x0, y0 = (y0 + y1) / 2), + p2 = radialPoint(x1, y0), + p3 = radialPoint(x1, y1); + context.moveTo(p0[0], p0[1]); + context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); +} + +function linkHorizontal() { + return link$2(curveHorizontal); +} + +function linkVertical() { + return link$2(curveVertical); +} + +function linkRadial() { + var l = link$2(curveRadial$1); + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + return l; +} + +var circle$2 = { + draw: function(context, size) { + var r = Math.sqrt(size / pi$4); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, tau$4); + } +}; + +var cross$2 = { + draw: function(context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); + } +}; + +var tan30 = Math.sqrt(1 / 3); +var tan30_2 = tan30 * 2; + +var diamond = { + draw: function(context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); + } +}; + +var ka = 0.89081309152928522810; +var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10); +var kx = Math.sin(tau$4 / 10) * kr; +var ky = -Math.cos(tau$4 / 10) * kr; + +var star = { + draw: function(context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = tau$4 * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); + } +}; + +var square = { + draw: function(context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); + } +}; + +var sqrt3 = Math.sqrt(3); + +var triangle = { + draw: function(context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } +}; + +var c = -0.5; +var s = Math.sqrt(3) / 2; +var k = 1 / Math.sqrt(12); +var a = (k / 2 + 1) * 3; + +var wye = { + draw: function(context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c * x0 - s * y0, s * x0 + c * y0); + context.lineTo(c * x1 - s * y1, s * x1 + c * y1); + context.lineTo(c * x2 - s * y2, s * x2 + c * y2); + context.lineTo(c * x0 + s * y0, c * y0 - s * x0); + context.lineTo(c * x1 + s * y1, c * y1 - s * x1); + context.lineTo(c * x2 + s * y2, c * y2 - s * x2); + context.closePath(); + } +}; + +var symbols = [ + circle$2, + cross$2, + diamond, + square, + star, + triangle, + wye +]; + +var symbol = function() { + var type = constant$10(circle$2), + size = constant$10(64), + context = null; + + function symbol() { + var buffer; + if (!context) context = buffer = path(); + type.apply(this, arguments).draw(context, +size.apply(this, arguments)); + if (buffer) return context = null, buffer + "" || null; + } + + symbol.type = function(_) { + return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type; + }; + + symbol.size = function(_) { + return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size; + }; + + symbol.context = function(_) { + return arguments.length ? (context = _ == null ? null : _, symbol) : context; + }; + + return symbol; +}; + +var noop$2 = function() {}; + +function point$2(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); +} + +function Basis(context) { + this._context = context; +} + +Basis.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 3: point$2(this, this._x1, this._y1); // proceed + case 2: this._context.lineTo(this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: point$2(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basis$2 = function(context) { + return new Basis(context); +}; + +function BasisClosed(context) { + this._context = context; +} + +BasisClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x2, this._y2); + this._context.closePath(); + break; + } + case 2: { + this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); + this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x2, this._y2); + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x2 = x, this._y2 = y; break; + case 1: this._point = 2; this._x3 = x, this._y3 = y; break; + case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; + default: point$2(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisClosed$1 = function(context) { + return new BasisClosed(context); +}; + +function BasisOpen(context) { + this._context = context; +} + +BasisOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; + case 3: this._point = 4; // proceed + default: point$2(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisOpen = function(context) { + return new BasisOpen(context); +}; + +function Bundle(context, beta) { + this._basis = new Basis(context); + this._beta = beta; +} + +Bundle.prototype = { + lineStart: function() { + this._x = []; + this._y = []; + this._basis.lineStart(); + }, + lineEnd: function() { + var x = this._x, + y = this._y, + j = x.length - 1; + + if (j > 0) { + var x0 = x[0], + y0 = y[0], + dx = x[j] - x0, + dy = y[j] - y0, + i = -1, + t; + + while (++i <= j) { + t = i / j; + this._basis.point( + this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), + this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) + ); + } + } + + this._x = this._y = null; + this._basis.lineEnd(); + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +var bundle = ((function custom(beta) { + + function bundle(context) { + return beta === 1 ? new Basis(context) : new Bundle(context, beta); + } + + bundle.beta = function(beta) { + return custom(+beta); + }; + + return bundle; +}))(0.85); + +function point$3(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); +} + +function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +Cardinal.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: point$3(this, this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; this._x1 = x, this._y1 = y; break; + case 2: this._point = 3; // proceed + default: point$3(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinal = ((function custom(tension) { + + function cardinal(context) { + return new Cardinal(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$3(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalClosed = ((function custom(tension) { + + function cardinal(context) { + return new CardinalClosed(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$3(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalOpen = ((function custom(tension) { + + function cardinal(context) { + return new CardinalOpen(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function point$4(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; + + if (that._l01_a > epsilon$3) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; + } + + if (that._l23_a > epsilon$3) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; + } + + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +} + +function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRom.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: this.point(this._x2, this._y2); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; // proceed + default: point$4(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRom = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function CatmullRomClosed(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$4(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomClosed = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function CatmullRomOpen(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$4(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomOpen = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function LinearClosed(context) { + this._context = context; +} + +LinearClosed.prototype = { + areaStart: noop$2, + areaEnd: noop$2, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._point) this._context.closePath(); + }, + point: function(x, y) { + x = +x, y = +y; + if (this._point) this._context.lineTo(x, y); + else this._point = 1, this._context.moveTo(x, y); + } +}; + +var linearClosed = function(context) { + return new LinearClosed(context); +}; + +function sign$1(x) { + return x < 0 ? -1 : 1; +} + +// Calculate the slopes of the tangents (Hermite-type interpolation) based on +// the following paper: Steffen, M. 1990. A Simple Method for Monotonic +// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. +// NOV(II), P. 443, 1990. +function slope3(that, x2, y2) { + var h0 = that._x1 - that._x0, + h1 = x2 - that._x1, + s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), + s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), + p = (s0 * h1 + s1 * h0) / (h0 + h1); + return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; +} + +// Calculate a one-sided slope. +function slope2(that, t) { + var h = that._x1 - that._x0; + return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; +} + +// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations +// "you can express cubic Hermite interpolation in terms of cubic Bézier curves +// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". +function point$5(that, t0, t1) { + var x0 = that._x0, + y0 = that._y0, + x1 = that._x1, + y1 = that._y1, + dx = (x1 - x0) / 3; + that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); +} + +function MonotoneX(context) { + this._context = context; +} + +MonotoneX.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = + this._t0 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x1, this._y1); break; + case 3: point$5(this, this._t0, slope2(this, this._t0)); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + var t1 = NaN; + + x = +x, y = +y; + if (x === this._x1 && y === this._y1) return; // Ignore coincident points. + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break; + default: point$5(this, this._t0, t1 = slope3(this, x, y)); break; + } + + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + this._t0 = t1; + } +}; + +function MonotoneY(context) { + this._context = new ReflectContext(context); +} + +(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { + MonotoneX.prototype.point.call(this, y, x); +}; + +function ReflectContext(context) { + this._context = context; +} + +ReflectContext.prototype = { + moveTo: function(x, y) { this._context.moveTo(y, x); }, + closePath: function() { this._context.closePath(); }, + lineTo: function(x, y) { this._context.lineTo(y, x); }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } +}; + +function monotoneX(context) { + return new MonotoneX(context); +} + +function monotoneY(context) { + return new MonotoneY(context); +} + +function Natural(context) { + this._context = context; +} + +Natural.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = []; + this._y = []; + }, + lineEnd: function() { + var x = this._x, + y = this._y, + n = x.length; + + if (n) { + this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); + if (n === 2) { + this._context.lineTo(x[1], y[1]); + } else { + var px = controlPoints(x), + py = controlPoints(y); + for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { + this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); + } + } + } + + if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); + this._line = 1 - this._line; + this._x = this._y = null; + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +// See https://www.particleincell.com/2012/bezier-splines/ for derivation. +function controlPoints(x) { + var i, + n = x.length - 1, + m, + a = new Array(n), + b = new Array(n), + r = new Array(n); + a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; + for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; + a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; + for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; + a[n - 1] = r[n - 1] / b[n - 1]; + for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; + b[n - 1] = (x[n] + a[n - 1]) / 2; + for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; + return [a, b]; +} + +var natural = function(context) { + return new Natural(context); +}; + +function Step(context, t) { + this._context = context; + this._t = t; +} + +Step.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = this._y = NaN; + this._point = 0; + }, + lineEnd: function() { + if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: { + if (this._t <= 0) { + this._context.lineTo(this._x, y); + this._context.lineTo(x, y); + } else { + var x1 = this._x * (1 - this._t) + x * this._t; + this._context.lineTo(x1, this._y); + this._context.lineTo(x1, y); + } + break; + } + } + this._x = x, this._y = y; + } +}; + +var step = function(context) { + return new Step(context, 0.5); +}; + +function stepBefore(context) { + return new Step(context, 0); +} + +function stepAfter(context) { + return new Step(context, 1); +} + +var none$1 = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + } + } +}; + +var none$2 = function(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) o[n] = n; + return o; +}; + +function stackValue(d, key) { + return d[key]; +} + +var stack = function() { + var keys = constant$10([]), + order = none$2, + offset = none$1, + value = stackValue; + + function stack(data) { + var kz = keys.apply(this, arguments), + i, + m = data.length, + n = kz.length, + sz = new Array(n), + oz; + + for (i = 0; i < n; ++i) { + for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { + si[j] = sij = [0, +value(data[j], ki, j, data)]; + sij.data = data[j]; + } + si.key = ki; + } + + for (i = 0, oz = order(sz); i < n; ++i) { + sz[oz[i]].index = i; + } + + offset(sz, oz); + return sz; + } + + stack.keys = function(_) { + return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : keys; + }; + + stack.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value; + }; + + stack.order = function(_) { + return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$5.call(_)), stack) : order; + }; + + stack.offset = function(_) { + return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset; + }; + + return stack; +}; + +var expand = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { + for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; + if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; + } + none$1(series, order); +}; + +var diverging = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { + for (yp = yn = 0, i = 0; i < n; ++i) { + if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { + d[0] = yp, d[1] = yp += dy; + } else if (dy < 0) { + d[1] = yn, d[0] = yn += dy; + } else { + d[0] = yp; + } + } + } +}; + +var silhouette = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { + for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; + s0[j][1] += s0[j][0] = -y / 2; + } + none$1(series, order); +}; + +var wiggle = function(series, order) { + if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; + for (var y = 0, j = 1, s0, m, n; j < m; ++j) { + for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { + var si = series[order[i]], + sij0 = si[j][1] || 0, + sij1 = si[j - 1][1] || 0, + s3 = (sij0 - sij1) / 2; + for (var k = 0; k < i; ++k) { + var sk = series[order[k]], + skj0 = sk[j][1] || 0, + skj1 = sk[j - 1][1] || 0; + s3 += skj0 - skj1; + } + s1 += sij0, s2 += s3 * sij0; + } + s0[j - 1][1] += s0[j - 1][0] = y; + if (s1) y -= s2 / s1; + } + s0[j - 1][1] += s0[j - 1][0] = y; + none$1(series, order); +}; + +var ascending$2 = function(series) { + var sums = series.map(sum$2); + return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; }); +}; + +function sum$2(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) if (v = +series[i][1]) s += v; + return s; +} + +var descending$2 = function(series) { + return ascending$2(series).reverse(); +}; + +var insideOut = function(series) { + var n = series.length, + i, + j, + sums = series.map(sum$2), + order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }), + top = 0, + bottom = 0, + tops = [], + bottoms = []; + + for (i = 0; i < n; ++i) { + j = order[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + + return bottoms.reverse().concat(tops); +}; + +var reverse = function(series) { + return none$2(series).reverse(); +}; + +var constant$11 = function(x) { + return function() { + return x; + }; +}; + +function x$4(d) { + return d[0]; +} + +function y$4(d) { + return d[1]; +} + +function RedBlackTree() { + this._ = null; // root node +} + +function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node +} + +RedBlackTree.prototype = { + constructor: RedBlackTree, + + insert: function(after, node) { + var parent, grandpa, uncle; + + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = RedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + + var parent = node.U, + sibling, + left = node.L, + right = node.R, + next, + red; + + if (!left) next = right; + else if (!right) next = left; + else next = RedBlackFirst(right); + + if (parent) { + if (parent.L === node) parent.L = next; + else parent.R = next; + } else { + this._ = next; + } + + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + + if (node) node.U = parent; + if (red) return; + if (node && node.C) { node.C = false; return; } + + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(this, parent); + sibling = parent.L; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + + if (node) node.C = false; + } +}; + +function RedBlackRotateLeft(tree, node) { + var p = node, + q = node.R, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; +} + +function RedBlackRotateRight(tree, node) { + var p = node, + q = node.L, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; +} + +function RedBlackFirst(node) { + while (node.L) node = node.L; + return node; +} + +function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = edges.push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) setEdgeEnd(edge, left, right, v0); + if (v1) setEdgeEnd(edge, right, left, v1); + cells[left.index].halfedges.push(index); + cells[right.index].halfedges.push(index); + return edge; +} + +function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; +} + +function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; + } else { + edge[0] = vertex; + } +} + +// Liang–Barsky line clipping. +function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check? + + if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; +} + +function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!v0) v0 = [fx, y0]; + else if (v0[1] >= y1) return; + v1 = [fx, y1]; + } else { + if (!v0) v0 = [fx, y1]; + else if (v0[1] < y0) return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) return; + v1 = [(y0 - fb) / fm, y0]; + } + } else { + if (ly < ry) { + if (!v0) v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) return; + v1 = [x0, fm * x0 + fb]; + } + } + } + + edge[0] = v0; + edge[1] = v1; + return true; +} + +function clipEdges(x0, y0, x1, y1) { + var i = edges.length, + edge; + + while (i--) { + if (!connectEdge(edge = edges[i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4 + || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) { + delete edges[i]; + } + } +} + +function createCell(site) { + return cells[site.index] = { + site: site, + halfedges: [] + }; +} + +function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) vb = va, va = site; + if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) va = edge[1], vb = edge[0]; + else va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); +} + +function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; +} + +function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; +} + +function sortCellHalfedges() { + for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); + index.sort(function(i, j) { return array[j] - array[i]; }); + for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) halfedges[j] = array[j]; + } + } +} + +function clipCells(x0, y0, x1, y1) { + var nCells = cells.length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; + + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; + + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!edges[halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } + + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) { + halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, + Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1] + : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1] + : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0] + : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } + + if (nHalfedges) cover = false; + } + } + + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, + edges.push(createBorderEdge(site, v01, v11)) - 1, + edges.push(createBorderEdge(site, v11, v10)) - 1, + edges.push(createBorderEdge(site, v10, v00)) - 1 + ); + } + } + + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + if (!cell.halfedges.length) { + delete cells[iCell]; + } + } + } +} + +var circlePool = []; + +var firstCircle; + +function Circle() { + RedBlackNode(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; +} + +function attachCircle(arc) { + var lArc = arc.P, + rArc = arc.N; + + if (!lArc || !rArc) return; + + var lSite = lArc.site, + cSite = arc.site, + rSite = rArc.site; + + if (lSite === rSite) return; + + var bx = cSite[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; + + var d = 2 * (ax * cy - ay * cx); + if (d >= -epsilon2$2) return; + + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; + + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom + + arc.circle = circle; + + var before = null, + node = circles._; + + while (node) { + if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { + if (node.L) node = node.L; + else { before = node.P; break; } + } else { + if (node.R) node = node.R; + else { before = node; break; } + } + } + + circles.insert(before, circle); + if (!before) firstCircle = circle; +} + +function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) firstCircle = circle.N; + circles.remove(circle); + circlePool.push(circle); + RedBlackNode(circle); + arc.circle = null; + } +} + +var beachPool = []; + +function Beach() { + RedBlackNode(this); + this.edge = + this.site = + this.circle = null; +} + +function createBeach(site) { + var beach = beachPool.pop() || new Beach; + beach.site = site; + return beach; +} + +function detachBeach(beach) { + detachCircle(beach); + beaches.remove(beach); + beachPool.push(beach); + RedBlackNode(beach); +} + +function removeBeach(beach) { + var circle = beach.circle, + x = circle.x, + y = circle.cy, + vertex = [x, y], + previous = beach.P, + next = beach.N, + disappearing = [beach]; + + detachBeach(beach); + + var lArc = previous; + while (lArc.circle + && Math.abs(x - lArc.circle.x) < epsilon$4 + && Math.abs(y - lArc.circle.cy) < epsilon$4) { + previous = lArc.P; + disappearing.unshift(lArc); + detachBeach(lArc); + lArc = previous; + } + + disappearing.unshift(lArc); + detachCircle(lArc); + + var rArc = next; + while (rArc.circle + && Math.abs(x - rArc.circle.x) < epsilon$4 + && Math.abs(y - rArc.circle.cy) < epsilon$4) { + next = rArc.N; + disappearing.push(rArc); + detachBeach(rArc); + rArc = next; + } + + disappearing.push(rArc); + detachCircle(rArc); + + var nArcs = disappearing.length, + iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); + + attachCircle(lArc); + attachCircle(rArc); +} + +function addBeach(site) { + var x = site[0], + directrix = site[1], + lArc, + rArc, + dxl, + dxr, + node = beaches._; + + while (node) { + dxl = leftBreakPoint(node, directrix) - x; + if (dxl > epsilon$4) node = node.L; else { + dxr = x - rightBreakPoint(node, directrix); + if (dxr > epsilon$4) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -epsilon$4) { + lArc = node.P; + rArc = node; + } else if (dxr > -epsilon$4) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + + createCell(site); + var newArc = createBeach(site); + beaches.insert(lArc, newArc); + + if (!lArc && !rArc) return; + + if (lArc === rArc) { + detachCircle(lArc); + rArc = createBeach(lArc.site); + beaches.insert(newArc, rArc); + newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); + attachCircle(lArc); + attachCircle(rArc); + return; + } + + if (!rArc) { // && lArc + newArc.edge = createEdge(lArc.site, newArc.site); + return; + } + + // else lArc !== rArc + detachCircle(lArc); + detachCircle(rArc); + + var lSite = lArc.site, + ax = lSite[0], + ay = lSite[1], + bx = site[0] - ax, + by = site[1] - ay, + rSite = rArc.site, + cx = rSite[0] - ax, + cy = rSite[1] - ay, + d = 2 * (bx * cy - by * cx), + hb = bx * bx + by * by, + hc = cx * cx + cy * cy, + vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; + + setEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = createEdge(lSite, site, null, vertex); + rArc.edge = createEdge(site, rSite, null, vertex); + attachCircle(lArc); + attachCircle(rArc); +} + +function leftBreakPoint(arc, directrix) { + var site = arc.site, + rfocx = site[0], + rfocy = site[1], + pby2 = rfocy - directrix; + + if (!pby2) return rfocx; + + var lArc = arc.P; + if (!lArc) return -Infinity; + + site = lArc.site; + var lfocx = site[0], + lfocy = site[1], + plby2 = lfocy - directrix; + + if (!plby2) return lfocx; + + var hl = lfocx - rfocx, + aby2 = 1 / pby2 - 1 / plby2, + b = hl / plby2; + + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + + return (rfocx + lfocx) / 2; +} + +function rightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return leftBreakPoint(rArc, directrix); + var site = arc.site; + return site[1] === directrix ? site[0] : Infinity; +} + +var epsilon$4 = 1e-6; +var epsilon2$2 = 1e-12; +var beaches; +var cells; +var circles; +var edges; + +function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); +} + +function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; +} + +function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; + + edges = []; + cells = new Array(sites.length); + beaches = new RedBlackTree; + circles = new RedBlackTree; + + while (true) { + circle = firstCircle; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + addBeach(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + removeBeach(circle.arc); + } else { + break; + } + } + + sortCellHalfedges(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + clipEdges(x0, y0, x1, y1); + clipCells(x0, y0, x1, y1); + } + + this.edges = edges; + this.cells = cells; + + beaches = + circles = + edges = + cells = null; +} + +Diagram.prototype = { + constructor: Diagram, + + polygons: function() { + var edges = this.edges; + + return this.cells.map(function(cell) { + var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); + polygon.data = cell.site.data; + return polygon; + }); + }, + + triangles: function() { + var triangles = [], + edges = this.edges; + + this.cells.forEach(function(cell, i) { + if (!(m = (halfedges = cell.halfedges).length)) return; + var site = cell.site, + halfedges, + j = -1, + m, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; + + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); + + return triangles; + }, + + links: function() { + return this.edges.filter(function(edge) { + return edge.right; + }).map(function(edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, + + find: function(x, y, radius) { + var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; + + // Use the previously-found cell, or start with an arbitrary one. + while (!(cell = that.cells[i1])) if (++i1 >= n) return null; + var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; + + // Traverse the half-edges to find a closer cell, if any. + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function(e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) return; + var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; + if (v2 < d2) d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; + + return radius == null || d2 <= radius * radius ? cell.site : null; + } +}; + +var voronoi = function() { + var x$$1 = x$4, + y$$1 = y$4, + extent = null; + + function voronoi(data) { + return new Diagram(data.map(function(d, i) { + var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4]; + s.index = i; + s.data = d; + return s; + }), extent); + } + + voronoi.polygons = function(data) { + return voronoi(data).polygons(); + }; + + voronoi.links = function(data) { + return voronoi(data).links(); + }; + + voronoi.triangles = function(data) { + return voronoi(data).triangles(); + }; + + voronoi.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x$$1; + }; + + voronoi.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y$$1; + }; + + voronoi.extent = function(_) { + return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; + }; + + voronoi.size = function(_) { + return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; + }; + + return voronoi; +}; + +var constant$12 = function(x) { + return function() { + return x; + }; +}; + +function ZoomEvent(target, type, transform) { + this.target = target; + this.type = type; + this.transform = transform; +} + +function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; +} + +Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } +}; + +var identity$8 = new Transform(1, 0, 0); + +transform$1.prototype = Transform.prototype; + +function transform$1(node) { + return node.__zoom || identity$8; +} + +function nopropagation$2() { + exports.event.stopImmediatePropagation(); +} + +var noevent$2 = function() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter$2() { + return !exports.event.button; +} + +function defaultExtent$1() { + var e = this, w, h; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + w = e.width.baseVal.value; + h = e.height.baseVal.value; + } else { + w = e.clientWidth; + h = e.clientHeight; + } + return [[0, 0], [w, h]]; +} + +function defaultTransform() { + return this.__zoom || identity$8; +} + +var zoom = function() { + var filter = defaultFilter$2, + extent = defaultExtent$1, + k0 = 0, + k1 = Infinity, + x0 = -k1, + x1 = k1, + y0 = x0, + y1 = x1, + duration = 250, + interpolate$$1 = interpolateZoom, + gestures = [], + listeners = dispatch("start", "zoom", "end"), + touchstarting, + touchending, + touchDelay = 500, + wheelDelay = 150, + clickDistance2 = 0; + + function zoom(selection$$1) { + selection$$1 + .on("wheel.zoom", wheeled) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .property("__zoom", defaultTransform); + } + + zoom.transform = function(collection, transform) { + var selection$$1 = collection.selection ? collection.selection() : collection; + selection$$1.property("__zoom", defaultTransform); + if (collection !== selection$$1) { + schedule(collection, transform); + } else { + selection$$1.interrupt().each(function() { + gesture(this, arguments) + .start() + .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) + .end(); + }); + } + }; + + zoom.scaleBy = function(selection$$1, k) { + zoom.scaleTo(selection$$1, function() { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }); + }; + + zoom.scaleTo = function(selection$$1, k) { + zoom.transform(selection$$1, function() { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = centroid(e), + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e); + }); + }; + + zoom.translateBy = function(selection$$1, x, y) { + zoom.transform(selection$$1, function() { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments)); + }); + }; + + function scale(transform, k) { + k = Math.max(k0, Math.min(k1, k)); + return k === transform.k ? transform : new Transform(k, transform.x, transform.y); + } + + function translate(transform, p0, p1) { + var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; + return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + } + + function constrain(transform, extent) { + var dx0 = transform.invertX(extent[0][0]) - x0, + dx1 = transform.invertX(extent[1][0]) - x1, + dy0 = transform.invertY(extent[0][1]) - y0, + dy1 = transform.invertY(extent[1][1]) - y1; + return transform.translate( + dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), + dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) + ); + } + + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } + + function schedule(transition$$1, transform, center) { + transition$$1 + .on("start.zoom", function() { gesture(this, arguments).start(); }) + .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) + .tween("zoom", function() { + var that = this, + args = arguments, + g = gesture(that, args), + e = extent.apply(that, args), + p = center || centroid(e), + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform === "function" ? transform.apply(that, args) : transform, + i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function(t) { + if (t === 1) t = b; // Avoid rounding error on end. + else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } + g.zoom(null, t); + }; + }); + } + + function gesture(that, args) { + for (var i = 0, n = gestures.length, g; i < n; ++i) { + if ((g = gestures[i]).that === that) { + return g; + } + } + return new Gesture(that, args); + } + + function Gesture(that, args) { + this.that = that; + this.args = args; + this.index = -1; + this.active = 0; + this.extent = extent.apply(that, args); + } + + Gesture.prototype = { + start: function() { + if (++this.active === 1) { + this.index = gestures.push(this) - 1; + this.emit("start"); + } + return this; + }, + zoom: function(key, transform) { + if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); + this.that.__zoom = transform; + this.emit("zoom"); + return this; + }, + end: function() { + if (--this.active === 0) { + gestures.splice(this.index, 1); + this.index = -1; + this.emit("end"); + } + return this; + }, + emit: function(type) { + customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function wheeled() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + t = this.__zoom, + k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -exports.event.deltaY * (exports.event.deltaMode ? 120 : 1) / 500))), + p = mouse(this); + + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } + + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) return; + + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + interrupt(this); + g.start(); + } + + noevent$2(); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent)); + + function wheelidled() { + g.wheel = null; + g.end(); + } + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = mouse(this), + x0 = exports.event.clientX, + y0 = exports.event.clientY; + + dragDisable(exports.event.view); + nopropagation$2(); + g.mouse = [p, this.__zoom.invert(p)]; + interrupt(this); + g.start(); + + function mousemoved() { + noevent$2(); + if (!g.moved) { + var dx = exports.event.clientX - x0, dy = exports.event.clientY - y0; + g.moved = dx * dx + dy * dy > clickDistance2; + } + g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent)); + } + + function mouseupped() { + v.on("mousemove.zoom mouseup.zoom", null); + yesdrag(exports.event.view, g.moved); + noevent$2(); + g.end(); + } + } + + function dblclicked() { + if (!filter.apply(this, arguments)) return; + var t0 = this.__zoom, + p0 = mouse(this), + p1 = t0.invert(p0), + k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments)); + + noevent$2(); + if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0); + else select(this).call(zoom.transform, t1); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + started, + n = touches$$1.length, i, t, p; + + nopropagation$2(); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) g.touch0 = p, started = true; + else if (!g.touch1) g.touch1 = p; + } + + // If this is a dbltap, reroute to the (optional) dblclick.zoom handler. + if (touchstarting) { + touchstarting = clearTimeout(touchstarting); + if (!g.touch1) { + g.end(); + p = select(this).on("dblclick.zoom"); + if (p) p.apply(this, arguments); + return; + } + } + + if (started) { + touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); + interrupt(this); + g.start(); + } + } + + function touchmoved() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t, p, l; + + noevent$2(); + if (touchstarting) touchstarting = clearTimeout(touchstarting); + for (i = 0; i < n; ++i) { + t = touches$$1[i], p = touch(this, touches$$1, t.identifier); + if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } + else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; + else return; + g.zoom("touch", constrain(translate(t, p, l), g.extent)); + } + + function touchended() { + var g = gesture(this, arguments), + touches$$1 = exports.event.changedTouches, + n = touches$$1.length, i, t; + + nopropagation$2(); + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches$$1[i]; + if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; + } + if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; + if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); + else g.end(); + } + + zoom.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter; + }; + + zoom.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; + + zoom.scaleExtent = function(_) { + return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1]; + }; + + zoom.translateExtent = function(_) { + return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]]; + }; + + zoom.duration = function(_) { + return arguments.length ? (duration = +_, zoom) : duration; + }; + + zoom.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1; + }; + + zoom.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + zoom.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); + }; + + return zoom; +}; + +exports.version = version; +exports.bisect = bisectRight; +exports.bisectRight = bisectRight; +exports.bisectLeft = bisectLeft; +exports.ascending = ascending; +exports.bisector = bisector; +exports.cross = cross; +exports.descending = descending; +exports.deviation = deviation; +exports.extent = extent; +exports.histogram = histogram; +exports.thresholdFreedmanDiaconis = freedmanDiaconis; +exports.thresholdScott = scott; +exports.thresholdSturges = sturges; +exports.max = max; +exports.mean = mean; +exports.median = median; +exports.merge = merge; +exports.min = min; +exports.pairs = pairs; +exports.permute = permute; +exports.quantile = threshold; +exports.range = sequence; +exports.scan = scan; +exports.shuffle = shuffle; +exports.sum = sum; +exports.ticks = ticks; +exports.tickIncrement = tickIncrement; +exports.tickStep = tickStep; +exports.transpose = transpose; +exports.variance = variance; +exports.zip = zip; +exports.axisTop = axisTop; +exports.axisRight = axisRight; +exports.axisBottom = axisBottom; +exports.axisLeft = axisLeft; +exports.brush = brush; +exports.brushX = brushX; +exports.brushY = brushY; +exports.brushSelection = brushSelection; +exports.chord = chord; +exports.ribbon = ribbon; +exports.nest = nest; +exports.set = set$2; +exports.map = map$1; +exports.keys = keys; +exports.values = values; +exports.entries = entries; +exports.color = color; +exports.rgb = rgb; +exports.hsl = hsl; +exports.lab = lab; +exports.hcl = hcl; +exports.cubehelix = cubehelix; +exports.dispatch = dispatch; +exports.drag = drag; +exports.dragDisable = dragDisable; +exports.dragEnable = yesdrag; +exports.dsvFormat = dsv; +exports.csvParse = csvParse; +exports.csvParseRows = csvParseRows; +exports.csvFormat = csvFormat; +exports.csvFormatRows = csvFormatRows; +exports.tsvParse = tsvParse; +exports.tsvParseRows = tsvParseRows; +exports.tsvFormat = tsvFormat; +exports.tsvFormatRows = tsvFormatRows; +exports.easeLinear = linear$1; +exports.easeQuad = quadInOut; +exports.easeQuadIn = quadIn; +exports.easeQuadOut = quadOut; +exports.easeQuadInOut = quadInOut; +exports.easeCubic = cubicInOut; +exports.easeCubicIn = cubicIn; +exports.easeCubicOut = cubicOut; +exports.easeCubicInOut = cubicInOut; +exports.easePoly = polyInOut; +exports.easePolyIn = polyIn; +exports.easePolyOut = polyOut; +exports.easePolyInOut = polyInOut; +exports.easeSin = sinInOut; +exports.easeSinIn = sinIn; +exports.easeSinOut = sinOut; +exports.easeSinInOut = sinInOut; +exports.easeExp = expInOut; +exports.easeExpIn = expIn; +exports.easeExpOut = expOut; +exports.easeExpInOut = expInOut; +exports.easeCircle = circleInOut; +exports.easeCircleIn = circleIn; +exports.easeCircleOut = circleOut; +exports.easeCircleInOut = circleInOut; +exports.easeBounce = bounceOut; +exports.easeBounceIn = bounceIn; +exports.easeBounceOut = bounceOut; +exports.easeBounceInOut = bounceInOut; +exports.easeBack = backInOut; +exports.easeBackIn = backIn; +exports.easeBackOut = backOut; +exports.easeBackInOut = backInOut; +exports.easeElastic = elasticOut; +exports.easeElasticIn = elasticIn; +exports.easeElasticOut = elasticOut; +exports.easeElasticInOut = elasticInOut; +exports.forceCenter = center$1; +exports.forceCollide = collide; +exports.forceLink = link; +exports.forceManyBody = manyBody; +exports.forceSimulation = simulation; +exports.forceX = x$2; +exports.forceY = y$2; +exports.formatDefaultLocale = defaultLocale; +exports.formatLocale = formatLocale; +exports.formatSpecifier = formatSpecifier; +exports.precisionFixed = precisionFixed; +exports.precisionPrefix = precisionPrefix; +exports.precisionRound = precisionRound; +exports.geoArea = area; +exports.geoBounds = bounds; +exports.geoCentroid = centroid; +exports.geoCircle = circle; +exports.geoClipExtent = extent$1; +exports.geoContains = contains; +exports.geoDistance = distance; +exports.geoGraticule = graticule; +exports.geoGraticule10 = graticule10; +exports.geoInterpolate = interpolate$1; +exports.geoLength = length$1; +exports.geoPath = index$1; +exports.geoAlbers = albers; +exports.geoAlbersUsa = albersUsa; +exports.geoAzimuthalEqualArea = azimuthalEqualArea; +exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; +exports.geoAzimuthalEquidistant = azimuthalEquidistant; +exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; +exports.geoConicConformal = conicConformal; +exports.geoConicConformalRaw = conicConformalRaw; +exports.geoConicEqualArea = conicEqualArea; +exports.geoConicEqualAreaRaw = conicEqualAreaRaw; +exports.geoConicEquidistant = conicEquidistant; +exports.geoConicEquidistantRaw = conicEquidistantRaw; +exports.geoEquirectangular = equirectangular; +exports.geoEquirectangularRaw = equirectangularRaw; +exports.geoGnomonic = gnomonic; +exports.geoGnomonicRaw = gnomonicRaw; +exports.geoIdentity = identity$5; +exports.geoProjection = projection; +exports.geoProjectionMutator = projectionMutator; +exports.geoMercator = mercator; +exports.geoMercatorRaw = mercatorRaw; +exports.geoOrthographic = orthographic; +exports.geoOrthographicRaw = orthographicRaw; +exports.geoStereographic = stereographic; +exports.geoStereographicRaw = stereographicRaw; +exports.geoTransverseMercator = transverseMercator; +exports.geoTransverseMercatorRaw = transverseMercatorRaw; +exports.geoRotation = rotation; +exports.geoStream = geoStream; +exports.geoTransform = transform; +exports.cluster = cluster; +exports.hierarchy = hierarchy; +exports.pack = index$2; +exports.packSiblings = siblings; +exports.packEnclose = enclose; +exports.partition = partition; +exports.stratify = stratify; +exports.tree = tree; +exports.treemap = index$3; +exports.treemapBinary = binary; +exports.treemapDice = treemapDice; +exports.treemapSlice = treemapSlice; +exports.treemapSliceDice = sliceDice; +exports.treemapSquarify = squarify; +exports.treemapResquarify = resquarify; +exports.interpolate = interpolateValue; +exports.interpolateArray = array$1; +exports.interpolateBasis = basis$1; +exports.interpolateBasisClosed = basisClosed; +exports.interpolateDate = date; +exports.interpolateNumber = reinterpolate; +exports.interpolateObject = object; +exports.interpolateRound = interpolateRound; +exports.interpolateString = interpolateString; +exports.interpolateTransformCss = interpolateTransformCss; +exports.interpolateTransformSvg = interpolateTransformSvg; +exports.interpolateZoom = interpolateZoom; +exports.interpolateRgb = interpolateRgb; +exports.interpolateRgbBasis = rgbBasis; +exports.interpolateRgbBasisClosed = rgbBasisClosed; +exports.interpolateHsl = hsl$2; +exports.interpolateHslLong = hslLong; +exports.interpolateLab = lab$1; +exports.interpolateHcl = hcl$2; +exports.interpolateHclLong = hclLong; +exports.interpolateCubehelix = cubehelix$2; +exports.interpolateCubehelixLong = cubehelixLong; +exports.quantize = quantize; +exports.path = path; +exports.polygonArea = area$1; +exports.polygonCentroid = centroid$1; +exports.polygonHull = hull; +exports.polygonContains = contains$1; +exports.polygonLength = length$2; +exports.quadtree = quadtree; +exports.queue = queue; +exports.randomUniform = uniform; +exports.randomNormal = normal; +exports.randomLogNormal = logNormal; +exports.randomBates = bates; +exports.randomIrwinHall = irwinHall; +exports.randomExponential = exponential$1; +exports.request = request; +exports.html = html; +exports.json = json; +exports.text = text; +exports.xml = xml; +exports.csv = csv$1; +exports.tsv = tsv$1; +exports.scaleBand = band; +exports.scalePoint = point$1; +exports.scaleIdentity = identity$6; +exports.scaleLinear = linear$2; +exports.scaleLog = log$1; +exports.scaleOrdinal = ordinal; +exports.scaleImplicit = implicit; +exports.scalePow = pow$1; +exports.scaleSqrt = sqrt$1; +exports.scaleQuantile = quantile$$1; +exports.scaleQuantize = quantize$1; +exports.scaleThreshold = threshold$1; +exports.scaleTime = time; +exports.scaleUtc = utcTime; +exports.schemeCategory10 = category10; +exports.schemeCategory20b = category20b; +exports.schemeCategory20c = category20c; +exports.schemeCategory20 = category20; +exports.interpolateCubehelixDefault = cubehelix$3; +exports.interpolateRainbow = rainbow$1; +exports.interpolateWarm = warm; +exports.interpolateCool = cool; +exports.interpolateViridis = viridis; +exports.interpolateMagma = magma; +exports.interpolateInferno = inferno; +exports.interpolatePlasma = plasma; +exports.scaleSequential = sequential; +exports.creator = creator; +exports.local = local$1; +exports.matcher = matcher$1; +exports.mouse = mouse; +exports.namespace = namespace; +exports.namespaces = namespaces; +exports.select = select; +exports.selectAll = selectAll; +exports.selection = selection; +exports.selector = selector; +exports.selectorAll = selectorAll; +exports.style = styleValue; +exports.touch = touch; +exports.touches = touches; +exports.window = defaultView; +exports.customEvent = customEvent; +exports.arc = arc; +exports.area = area$2; +exports.line = line; +exports.pie = pie; +exports.radialArea = radialArea; +exports.radialLine = radialLine$1; +exports.linkHorizontal = linkHorizontal; +exports.linkVertical = linkVertical; +exports.linkRadial = linkRadial; +exports.symbol = symbol; +exports.symbols = symbols; +exports.symbolCircle = circle$2; +exports.symbolCross = cross$2; +exports.symbolDiamond = diamond; +exports.symbolSquare = square; +exports.symbolStar = star; +exports.symbolTriangle = triangle; +exports.symbolWye = wye; +exports.curveBasisClosed = basisClosed$1; +exports.curveBasisOpen = basisOpen; +exports.curveBasis = basis$2; +exports.curveBundle = bundle; +exports.curveCardinalClosed = cardinalClosed; +exports.curveCardinalOpen = cardinalOpen; +exports.curveCardinal = cardinal; +exports.curveCatmullRomClosed = catmullRomClosed; +exports.curveCatmullRomOpen = catmullRomOpen; +exports.curveCatmullRom = catmullRom; +exports.curveLinearClosed = linearClosed; +exports.curveLinear = curveLinear; +exports.curveMonotoneX = monotoneX; +exports.curveMonotoneY = monotoneY; +exports.curveNatural = natural; +exports.curveStep = step; +exports.curveStepAfter = stepAfter; +exports.curveStepBefore = stepBefore; +exports.stack = stack; +exports.stackOffsetExpand = expand; +exports.stackOffsetDiverging = diverging; +exports.stackOffsetNone = none$1; +exports.stackOffsetSilhouette = silhouette; +exports.stackOffsetWiggle = wiggle; +exports.stackOrderAscending = ascending$2; +exports.stackOrderDescending = descending$2; +exports.stackOrderInsideOut = insideOut; +exports.stackOrderNone = none$2; +exports.stackOrderReverse = reverse; +exports.timeInterval = newInterval; +exports.timeMillisecond = millisecond; +exports.timeMilliseconds = milliseconds; +exports.utcMillisecond = millisecond; +exports.utcMilliseconds = milliseconds; +exports.timeSecond = second; +exports.timeSeconds = seconds; +exports.utcSecond = second; +exports.utcSeconds = seconds; +exports.timeMinute = minute; +exports.timeMinutes = minutes; +exports.timeHour = hour; +exports.timeHours = hours; +exports.timeDay = day; +exports.timeDays = days; +exports.timeWeek = sunday; +exports.timeWeeks = sundays; +exports.timeSunday = sunday; +exports.timeSundays = sundays; +exports.timeMonday = monday; +exports.timeMondays = mondays; +exports.timeTuesday = tuesday; +exports.timeTuesdays = tuesdays; +exports.timeWednesday = wednesday; +exports.timeWednesdays = wednesdays; +exports.timeThursday = thursday; +exports.timeThursdays = thursdays; +exports.timeFriday = friday; +exports.timeFridays = fridays; +exports.timeSaturday = saturday; +exports.timeSaturdays = saturdays; +exports.timeMonth = month; +exports.timeMonths = months; +exports.timeYear = year; +exports.timeYears = years; +exports.utcMinute = utcMinute; +exports.utcMinutes = utcMinutes; +exports.utcHour = utcHour; +exports.utcHours = utcHours; +exports.utcDay = utcDay; +exports.utcDays = utcDays; +exports.utcWeek = utcSunday; +exports.utcWeeks = utcSundays; +exports.utcSunday = utcSunday; +exports.utcSundays = utcSundays; +exports.utcMonday = utcMonday; +exports.utcMondays = utcMondays; +exports.utcTuesday = utcTuesday; +exports.utcTuesdays = utcTuesdays; +exports.utcWednesday = utcWednesday; +exports.utcWednesdays = utcWednesdays; +exports.utcThursday = utcThursday; +exports.utcThursdays = utcThursdays; +exports.utcFriday = utcFriday; +exports.utcFridays = utcFridays; +exports.utcSaturday = utcSaturday; +exports.utcSaturdays = utcSaturdays; +exports.utcMonth = utcMonth; +exports.utcMonths = utcMonths; +exports.utcYear = utcYear; +exports.utcYears = utcYears; +exports.timeFormatDefaultLocale = defaultLocale$1; +exports.timeFormatLocale = formatLocale$1; +exports.isoFormat = formatIso; +exports.isoParse = parseIso; +exports.now = now; +exports.timer = timer; +exports.timerFlush = timerFlush; +exports.timeout = timeout$1; +exports.interval = interval$1; +exports.transition = transition; +exports.active = active; +exports.interrupt = interrupt; +exports.voronoi = voronoi; +exports.zoom = zoom; +exports.zoomTransform = transform$1; +exports.zoomIdentity = identity$8; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/examples/js/lib/d3.v4.min.js b/examples/js/lib/d3.v4.min.js new file mode 100644 index 0000000..6a78c32 --- /dev/null +++ b/examples/js/lib/d3.v4.min.js @@ -0,0 +1,8 @@ +// https://d3js.org Version 4.3.0. Copyright 2016 Mike Bostock. +(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return Ms(t(n),e)}}function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Fs?i*=10:o>=Is?i*=5:o>=Ys&&(i*=2),n1&&Wf(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function q(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}function L(){return new q}function R(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u;while((l=f<<1|s)===(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function U(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-(1/0),l=-(1/0);for(e=0;ef&&(f=r),il&&(l=i));for(f=1))throw new Error;this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function H(t){if(!t._start)try{X(t)}catch(n){if(t._tasks[t._ended+t._active-1])W(t,n);else if(!t._data)throw n}}function X(t){for(;t._start=t._waiting&&t._active=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(t){}t._active=NaN,$(t)}function $(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Z(t){return new j(arguments.length?+t:1/0)}function G(t){return t.innerRadius}function J(t){return t.outerRadius}function Q(t){return t.startAngle}function K(t){return t.endAngle}function tt(t){return t&&t.padAngle}function nt(t){return t>=1?xl:t<=-1?-xl:Math.asin(t)}function et(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function rt(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*Math.sqrt(Math.max(0,b*b*x-w*w)),T=(w*m-g*M)/x,N=(-w*g-m*M)/x,k=(w*m+g*M)/x,S=(-w*g+m*M)/x,A=T-_,E=N-y,C=k-_,z=S-y;return A*A+E*E>C*C+z*z&&(T=k,N=S),{cx:T,cy:N,x01:-f,y01:-l,x11:T*(i/b-1),y11:N*(i/b-1)}}function it(t){this._context=t}function ot(t){return t[0]}function ut(t){return t[1]}function at(t){this._curve=t}function ct(t){function n(n){return new at(t(n))}return n._curve=t,n}function st(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(ct(t)):n()._curve},t}function ft(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function lt(t){this._context=t}function ht(t){this._context=t}function pt(t){this._context=t}function dt(t,n){this._basis=new lt(t),this._beta=n}function vt(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function _t(t,n){this._context=t,this._k=(1-n)/6}function yt(t,n){this._context=t,this._k=(1-n)/6}function gt(t,n){this._context=t,this._k=(1-n)/6}function mt(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>gl){var a=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*a-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*a-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>gl){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*s+t._x1*t._l23_2a-n*t._l12_2a)/f,u=(u*s+t._y1*t._l23_2a-e*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,u,t._x2,t._y2)}function xt(t,n){this._context=t,this._alpha=n}function bt(t,n){this._context=t,this._alpha=n}function wt(t,n){this._context=t,this._alpha=n}function Mt(t){this._context=t}function Tt(t){return t<0?-1:1}function Nt(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),u=(e-t._y1)/(i||r<0&&-0),a=(o*i+u*r)/(r+i);return(Tt(o)+Tt(u))*Math.min(Math.abs(o),Math.abs(u),.5*Math.abs(a))||0}function kt(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function St(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._context.bezierCurveTo(r+a,i+a*n,o-a,u-a*e,o,u)}function At(t){this._context=t}function Et(t){this._context=new Ct(t)}function Ct(t){this._context=t}function zt(t){return new At(t)}function Pt(t){return new Et(t)}function qt(t){this._context=t}function Lt(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new Array(r);for(i[0]=0,o[0]=2,u[0]=t[0]+2*t[1],n=1;n=0;--n)i[n]=(u[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=Sh.exec(t))?jt(parseInt(n[1],16)):(n=Ah.exec(t))?new Wt(n[1],n[2],n[3],1):(n=Eh.exec(t))?new Wt(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=Ch.exec(t))?Ht(n[1],n[2],n[3],n[4]):(n=zh.exec(t))?Ht(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Ph.exec(t))?$t(n[1],n[2]/100,n[3]/100,1):(n=qh.exec(t))?$t(n[1],n[2]/100,n[3]/100,n[4]):Lh.hasOwnProperty(t)?jt(Lh[t]):"transparent"===t?new Wt(NaN,NaN,NaN,0):null}function jt(t){return new Wt(t>>16&255,t>>8&255,255&t,1)}function Ht(t,n,e,r){return r<=0&&(t=n=e=NaN),new Wt(t,n,e,r)}function Xt(t){return t instanceof Yt||(t=Bt(t)),t?(t=t.rgb(),new Wt(t.r,t.g,t.b,t.opacity)):new Wt}function Vt(t,n,e,r){return 1===arguments.length?Xt(t):new Wt(t,n,e,null==r?1:r)}function Wt(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function $t(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Jt(t,n,e,r)}function Zt(t){if(t instanceof Jt)return new Jt(t.h,t.s,t.l,t.opacity);if(t instanceof Yt||(t=Bt(t)),!t)return new Jt;if(t instanceof Jt)return t;t=t.rgb();var n=t.r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e0&&c<1?0:u,new Jt(u,a,c,t.opacity)}function Gt(t,n,e,r){return 1===arguments.length?Zt(t):new Jt(t,n,e,null==r?1:r)}function Jt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Qt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function Kt(t){if(t instanceof nn)return new nn(t.l,t.a,t.b,t.opacity);if(t instanceof sn){var n=t.h*Rh;return new nn(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof Wt||(t=Xt(t));var e=un(t.r),r=un(t.g),i=un(t.b),o=en((.4124564*e+.3575761*r+.1804375*i)/Oh),u=en((.2126729*e+.7151522*r+.072175*i)/Fh),a=en((.0193339*e+.119192*r+.9503041*i)/Ih);return new nn(116*u-16,500*(o-u),200*(u-a),t.opacity)}function tn(t,n,e,r){return 1===arguments.length?Kt(t):new nn(t,n,e,null==r?1:r)}function nn(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function en(t){return t>Hh?Math.pow(t,1/3):t/jh+Yh}function rn(t){return t>Bh?t*t*t:jh*(t-Yh)}function on(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function un(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function an(t){if(t instanceof sn)return new sn(t.h,t.c,t.l,t.opacity);t instanceof nn||(t=Kt(t));var n=Math.atan2(t.b,t.a)*Uh;return new sn(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function cn(t,n,e,r){return 1===arguments.length?an(t):new sn(t,n,e,null==r?1:r)}function sn(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function fn(t){if(t instanceof hn)return new hn(t.h,t.s,t.l,t.opacity);t instanceof Wt||(t=Xt(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(Qh*r+Gh*n-Jh*e)/(Qh+Gh-Jh),o=r-i,u=(Zh*(e-i)-Wh*o)/$h,a=Math.sqrt(u*u+o*o)/(Zh*i*(1-i)),c=a?Math.atan2(u,o)*Uh-120:NaN;return new hn(c<0?c+360:c,a,i,t.opacity)}function ln(t,n,e,r){return 1===arguments.length?fn(t):new hn(t,n,e,null==r?1:r)}function hn(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function pn(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function dn(t,n){return function(e){return t+e*n}}function vn(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}function _n(t,n){var e=n-t;return e?dn(t,e>180||e<-180?e-360*Math.round(e/360):e):op(isNaN(t)?n:t)}function yn(t){return 1===(t=+t)?gn:function(n,e){return e-n?vn(n,e,t):op(isNaN(n)?e:n)}}function gn(t,n){var e=n-t;return e?dn(t,e):op(isNaN(t)?n:t)}function mn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:lp(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}function a(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:lp(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}function c(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:lp(t,e)},{i:a-2,x:lp(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}return function(n,e){var r=[],i=[];return n=t(n),e=t(e),o(n.translateX,n.translateY,e.translateX,e.translateY,r,i),u(n.rotate,e.rotate,r,i),a(n.skewX,e.skewX,r,i),c(n.scaleX,n.scaleY,e.scaleX,e.scaleY,r,i),n=e=null,function(t){for(var n,e=-1,o=i.length;++e=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}function Rn(t,n){for(var e,r=0,i=t.length;r=0&&n._call.call(null,t),n=n._next;--id}function $n(){sd=(cd=ld.now())+fd,id=od=0;try{Wn()}finally{id=0,Gn(),sd=0}}function Zn(){var t=ld.now(),n=t-cd;n>ad&&(fd-=n,cd=t)}function Gn(){for(var t,n,e=Up,r=1/0;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Up=n);Dp=t,Jn(r)}function Jn(t){if(!id){od&&(od=clearTimeout(od));var n=t-sd;n>24?(t<1/0&&(od=setTimeout($n,n)),ud&&(ud=clearInterval(ud))):(ud||(ud=setInterval(Zn,ad)),id=1,hd($n))}}function Qn(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n0))return u;do u.push(new Date(+e));while(n(e,o),t(e),e=n)for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){if(t>=t)for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return vd.setTime(+n),_d.setTime(+r),t(vd),t(_d),Math.floor(e(vd,_d))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t===0}:function(n){return i.count(0,n)%t===0}):i:null}),i}function Kn(t){return Qn(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*xd)/Md})}function te(t){return Qn(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/Md})}function ne(t){if(!(n=Av.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",u=!!n[5],a=n[6]&&+n[6],c=!!n[7],s=n[8]&&+n[8].slice(1),f=n[9]||"";"n"===f?(c=!0,f="g"):Sv[f]||(f=""),(u||"0"===e&&"="===r)&&(u=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=u,this.width=a,this.comma=c,this.precision=s,this.type=f}function ee(t){return t}function re(n){return Cv=Pv(n),t.format=Cv.format,t.formatPrefix=Cv.formatPrefix,Cv}function ie(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function oe(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function ue(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function ae(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=0,s=t.length;for(e instanceof Date||(e=new Date(+e));++a=c)return-1;if(i=n.charCodeAt(u++),37===i){if(i=n.charAt(u++),o=B[i in Dv?n.charAt(u++):i],!o||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function i(t,n,e){var r=C.exec(n.slice(e));return r?(t.p=z[r[0].toLowerCase()],e+r[0].length):-1}function o(t,n,e){var r=L.exec(n.slice(e));return r?(t.w=R[r[0].toLowerCase()],e+r[0].length):-1}function u(t,n,e){var r=P.exec(n.slice(e));return r?(t.w=q[r[0].toLowerCase()],e+r[0].length):-1}function a(t,n,e){var r=O.exec(n.slice(e));return r?(t.m=F[r[0].toLowerCase()],e+r[0].length):-1}function c(t,n,e){var r=U.exec(n.slice(e));return r?(t.m=D[r[0].toLowerCase()],e+r[0].length):-1}function s(t,n,e){return r(t,w,n,e)}function f(t,n,e){return r(t,M,n,e)}function l(t,n,e){return r(t,T,n,e)}function h(t){return S[t.getDay()]}function p(t){return k[t.getDay()]}function d(t){return E[t.getMonth()]}function v(t){return A[t.getMonth()]}function _(t){return N[+(t.getHours()>=12)]}function y(t){return S[t.getUTCDay()]}function g(t){return k[t.getUTCDay()]}function m(t){return E[t.getUTCMonth()]}function x(t){return A[t.getUTCMonth()]}function b(t){return N[+(t.getUTCHours()>=12)]}var w=t.dateTime,M=t.date,T=t.time,N=t.periods,k=t.days,S=t.shortDays,A=t.months,E=t.shortMonths,C=fe(N),z=le(N),P=fe(k),q=le(k),L=fe(S),R=le(S),U=fe(A),D=le(A),O=fe(E),F=le(E),I={a:h,A:p,b:d,B:v,c:null,d:ke,e:ke,H:Se,I:Ae,j:Ee,L:Ce,m:ze,M:Pe,p:_,S:qe,U:Le,w:Re,W:Ue,x:null,X:null,y:De,Y:Oe,Z:Fe,"%":tr},Y={a:y,A:g,b:m,B:x,c:null,d:Ie,e:Ie,H:Ye,I:Be,j:je,L:He,m:Xe,M:Ve,p:b,S:We,U:$e,w:Ze,W:Ge,x:null,X:null,y:Je,Y:Qe,Z:Ke,"%":tr},B={a:o,A:u,b:a,B:c,c:s,d:me,e:me,H:be,I:be,j:xe,L:Te,m:ge,M:we,p:i,S:Me,U:pe,w:he,W:de,x:f,X:l,y:_e,Y:ve,Z:ye,"%":Ne};return I.x=n(M,I),I.X=n(T,I),I.c=n(w,I),Y.x=n(M,Y),Y.X=n(T,Y),Y.c=n(w,Y),{format:function(t){var e=n(t+="",I);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",ie);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",Y);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,oe);return n.toString=function(){return t},n}}}function ce(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o68?1900:2e3),e+r[0].length):-1}function ye(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function ge(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function xe(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function be(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function we(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function Te(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function Ne(t,n,e){var r=Fv.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function ke(t,n){return ce(t.getDate(),n,2)}function Se(t,n){return ce(t.getHours(),n,2)}function Ae(t,n){return ce(t.getHours()%12||12,n,2)}function Ee(t,n){return ce(1+Cd.count($d(t),t),n,3)}function Ce(t,n){return ce(t.getMilliseconds(),n,3)}function ze(t,n){return ce(t.getMonth()+1,n,2)}function Pe(t,n){return ce(t.getMinutes(),n,2)}function qe(t,n){return ce(t.getSeconds(),n,2)}function Le(t,n){return ce(Pd.count($d(t),t),n,2)}function Re(t){return t.getDay()}function Ue(t,n){return ce(qd.count($d(t),t),n,2)}function De(t,n){return ce(t.getFullYear()%100,n,2)}function Oe(t,n){return ce(t.getFullYear()%1e4,n,4)}function Fe(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+ce(n/60|0,"0",2)+ce(n%60,"0",2)}function Ie(t,n){return ce(t.getUTCDate(),n,2)}function Ye(t,n){return ce(t.getUTCHours(),n,2)}function Be(t,n){return ce(t.getUTCHours()%12||12,n,2)}function je(t,n){return ce(1+tv.count(gv(t),t),n,3)}function He(t,n){return ce(t.getUTCMilliseconds(),n,3)}function Xe(t,n){return ce(t.getUTCMonth()+1,n,2)}function Ve(t,n){return ce(t.getUTCMinutes(),n,2)}function We(t,n){return ce(t.getUTCSeconds(),n,2)}function $e(t,n){return ce(ev.count(gv(t),t),n,2)}function Ze(t){return t.getUTCDay()}function Ge(t,n){return ce(rv.count(gv(t),t),n,2)}function Je(t,n){return ce(t.getUTCFullYear()%100,n,2)}function Qe(t,n){return ce(t.getUTCFullYear()%1e4,n,4)}function Ke(){return"+0000"}function tr(){return"%"}function nr(n){return qv=ae(n),t.timeFormat=qv.format,t.timeParse=qv.parse,t.utcFormat=qv.utcFormat,t.utcParse=qv.utcParse,qv}function er(t){return t.toISOString()}function rr(t){var n=new Date(t);return isNaN(n)?null:n}function ir(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==Wv)return i;e.set(o,u=r.push(n))}return t[(u-1)%t.length]}var e=o(),r=[],i=Wv;return t=null==t?[]:Vv.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=o();for(var i,u,a=-1,c=t.length;++a=e?1:r(t)}}}function fr(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}function lr(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o2?hr:lr,o=u=null,r}function r(n){return(o||(o=i(a,c,f?sr(t):t,s)))(+n)}var i,o,u,a=Gv,c=Gv,s=_p,f=!1;return r.invert=function(t){return(u||(u=i(c,a,cr,f?fr(n):n)))(+t)},r.domain=function(t){return arguments.length?(a=Xv.call(t,Zv),e()):a.slice()},r.range=function(t){return arguments.length?(c=Vv.call(t),e()):c.slice()},r.rangeRound=function(t){return c=Vv.call(t),s=yp,e()},r.clamp=function(t){return arguments.length?(f=!!t,e()):f},r.interpolate=function(t){return arguments.length?(s=t,e()):s},e()}function vr(t){var n=t.domain;return t.ticks=function(t){var e=n();return Bs(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){return Jv(n(),t,e)},t.nice=function(r){var i=n(),o=i.length-1,u=null==r?10:r,a=i[0],c=i[o],s=e(a,c,u);return s&&(s=e(Math.floor(a/s)*s,Math.ceil(c/s)*s,u),i[0]=Math.floor(a/s)*s,i[o]=Math.ceil(c/s)*s,n(i)),t},t}function _r(){var t=dr(cr,lp);return t.copy=function(){return pr(t,_r())},vr(t)}function yr(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=Xv.call(e,Zv),t):n.slice()},t.copy=function(){return yr().domain(n)},vr(t)}function gr(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t)/n}:$v(n)}function mr(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-t,1-e)}:function(e){return Math.pow(n,e)*Math.pow(t,1-e)}}function xr(t){return isFinite(t)?+("1e"+t):t<0?0:t}function br(t){return 10===t?xr:t===Math.E?Math.exp:function(n){return Math.pow(t,n)}}function wr(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(n){return Math.log(n)/t})}function Mr(t){return function(n){return-t(-n)}}function Tr(){function n(){return o=wr(i),u=br(i),r()[0]<0&&(o=Mr(o),u=Mr(u)),e}var e=dr(gr,mr).domain([1,10]),r=e.domain,i=10,o=wr(10),u=br(10);return e.base=function(t){return arguments.length?(i=+t,n()):i},e.domain=function(t){return arguments.length?(r(t),n()):r()},e.ticks=function(t){var n,e=r(),a=e[0],c=e[e.length-1];(n=c0){for(;hc)break;v.push(l)}}else for(;h=1;--f)if(l=s*f,!(lc)break;v.push(l)}}else v=Bs(h,p,Math.min(p-h,d)).map(u);return n?v.reverse():v},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var a=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/u(Math.round(o(t)));return n*i0?i[n-1]:e[0],n=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return Er().domain([e,r]).range(u)},vr(t)}function Cr(){function t(t){if(t<=t)return e[ks(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=Vv.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=Vv.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return Cr().domain(n).range(e)},t}function zr(t){return new Date(t); +}function Pr(t){return t instanceof Date?+t:+new Date(+t)}function qr(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function jr(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;rn?1:t>=n?0:NaN}function Qr(t){return function(){this.removeAttribute(t)}}function Kr(t){return function(){this.removeAttributeNS(t.space,t.local)}}function ti(t,n){return function(){this.setAttribute(t,n)}}function ni(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function ei(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function ri(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function ii(t){return function(){this.style.removeProperty(t)}}function oi(t,n,e){return function(){this.style.setProperty(t,n,e)}}function ui(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function ai(t){return function(){delete this[t]}}function ci(t,n){return function(){this[t]=n}}function si(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function fi(t){return t.trim().split(/^|\s+/)}function li(t){return t.classList||new hi(t)}function hi(t){this._node=t,this._names=fi(t.getAttribute("class")||"")}function pi(t,n){for(var e=li(t),r=-1,i=n.length;++rTy)throw new Error("too late");return e}function Li(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>ky)throw new Error("too late");return e}function Ri(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("too late");return e}function Ui(t,n,e){function r(t){e.state=Ny,e.timer.restart(i,e.delay,e.time),e.delay<=t&&i(t-e.delay)}function i(r){var s,f,l,h;if(e.state!==Ny)return u();for(s in c)if(h=c[s],h.name===e.name){if(h.state===Sy)return pd(i);h.state===Ay?(h.state=Cy,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete c[s]):+s=0&&(t=t.slice(0,n)),!t||"start"===t})}function to(t,n,e){var r,i,o=Ki(n)?qi:Li;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}function no(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}function eo(t,n){var e,r,i;return function(){var o=iy(this).getComputedStyle(this,null),u=o.getPropertyValue(t),a=(this.style.removeProperty(t),o.getPropertyValue(t));return u===a?null:u===e&&a===r?i:i=n(e=u,r=a)}}function ro(t){return function(){this.style.removeProperty(t)}}function io(t,n,e){var r,i;return function(){var o=iy(this).getComputedStyle(this,null).getPropertyValue(t);return o===e?null:o===r?i:i=n(r=o,e)}}function oo(t,n,e){var r,i,o;return function(){var u=iy(this).getComputedStyle(this,null),a=u.getPropertyValue(t),c=e(this);return null==c&&(this.style.removeProperty(t),c=u.getPropertyValue(t)),a===c?null:a===r&&c===i?o:o=n(r=a,i=c)}}function uo(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}function ao(t){return function(){this.textContent=t}}function co(t){return function(){var n=t(this);this.textContent=null==n?"":n}}function so(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function fo(t){return Pi().transition(t)}function lo(){return++Ky}function ho(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return ng.time=jn(),ng;return e}function po(t,n,e){var r=t(e);return"translate("+(isFinite(r)?r:n(e))+",0)"}function vo(t,n,e){var r=t(e);return"translate(0,"+(isFinite(r)?r:n(e))+")"}function _o(t){var n=t.bandwidth()/2;return t.round()&&(n=Math.round(n)),function(e){return t(e)+n}}function yo(){return!this.__axis}function go(t,n){function e(e){var s,f=null==i?n.ticks?n.ticks.apply(n,r):n.domain():i,l=null==o?n.tickFormat?n.tickFormat.apply(n,r):ug:o,h=Math.max(u,0)+c,p=t===ag||t===sg?po:vo,d=n.range(),v=d[0]+.5,_=d[d.length-1]+.5,y=(n.bandwidth?_o:ug)(n.copy()),g=e.selection?e.selection():e,m=g.selectAll(".domain").data([null]),x=g.selectAll(".tick").data(f,n).order(),b=x.exit(),w=x.enter().append("g").attr("class","tick"),M=x.select("line"),T=x.select("text"),N=t===ag||t===fg?-1:1,k=t===fg||t===cg?(s="x","y"):(s="y","x");m=m.merge(m.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),x=x.merge(w),M=M.merge(w.append("line").attr("stroke","#000").attr(s+"2",N*u).attr(k+"1",.5).attr(k+"2",.5)),T=T.merge(w.append("text").attr("fill","#000").attr(s,N*h).attr(k,.5).attr("dy",t===ag?"0em":t===sg?"0.71em":"0.32em")),e!==g&&(m=m.transition(e),x=x.transition(e),M=M.transition(e),T=T.transition(e),b=b.transition(e).attr("opacity",lg).attr("transform",function(t){return p(y,this.parentNode.__axis||y,t)}),w.attr("opacity",lg).attr("transform",function(t){return p(this.parentNode.__axis||y,y,t)})),b.remove(),m.attr("d",t===fg||t==cg?"M"+N*a+","+v+"H0.5V"+_+"H"+N*a:"M"+v+","+N*a+"V0.5H"+_+"V"+N*a),x.attr("opacity",1).attr("transform",function(t){return p(y,y,t)}),M.attr(s+"2",N*u),T.attr(s,N*h).text(l),g.filter(yo).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===cg?"start":t===fg?"end":"middle"),g.each(function(){this.__axis=y})}var r=[],i=null,o=null,u=6,a=6,c=3;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=og.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:og.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(i=null==t?null:og.call(t),e):i&&i.slice()},e.tickFormat=function(t){return arguments.length?(o=t,e):o},e.tickSize=function(t){return arguments.length?(u=a=+t,e):u},e.tickSizeInner=function(t){return arguments.length?(u=+t,e):u},e.tickSizeOuter=function(t){return arguments.length?(a=+t,e):a},e.tickPadding=function(t){return arguments.length?(c=+t,e):c},e}function mo(t){return go(ag,t)}function xo(t){return go(cg,t)}function bo(t){return go(sg,t)}function wo(t){return go(fg,t)}function Mo(t,n){return t.parent===n.parent?1:2}function To(t){return t.reduce(No,0)/t.length}function No(t,n){return t+n.x}function ko(t){return 1+t.reduce(So,0)}function So(t,n){return Math.max(t,n.y)}function Ao(t){for(var n;n=t.children;)t=n[0];return t}function Eo(t){for(var n;n=t.children;)t=n[n.length-1];return t}function Co(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}function zo(t,n){var e,r,i,o,u,a=new Uo(t),c=+t.value&&(a.value=t.value),s=[a];for(null==n&&(n=qo);e=s.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)s.push(r=e.children[o]=new Uo(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(Ro)}function Po(){return zo(this).eachBefore(Lo)}function qo(t){return t.children}function Lo(t){t.data=t.data.data}function Ro(t){var n=0;do t.height=n;while((t=t.parent)&&t.height<++n)}function Uo(t){this.data=t,this.depth=this.height=0,this.parent=null}function Do(t){this._=t,this.next=null}function Oo(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r-n.r;return i*i+1e-6>e*e+r*r}function Fo(t,n){var e,r,i,o=null,u=t.head;switch(n.length){case 1:e=Io(n[0]);break;case 2:e=Yo(n[0],n[1]);break;case 3:e=Bo(n[0],n[1],n[2])}for(;u;)i=u._,r=u.next,e&&Oo(e,i)?o=u:(o?(t.tail=o,o.next=null):t.head=t.tail=null,n.push(i),e=Fo(t,n),n.pop(),t.head?(u.next=t.head,t.head=u):(u.next=null,t.head=t.tail=u),o=t.tail,o.next=r),u=r;return t.tail=o,e}function Io(t){return{x:t.x,y:t.y,r:t.r}}function Yo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a-i,l=Math.sqrt(c*c+s*s);return{x:(e+o+c/l*f)/2,y:(r+u+s/l*f)/2,r:(l+i+a)/2}}function Bo(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l=e.r,h=2*(r-u),p=2*(i-a),d=2*(c-o),v=r*r+i*i-o*o-u*u-a*a+c*c,_=2*(r-s),y=2*(i-f),g=2*(l-o),m=r*r+i*i-o*o-s*s-f*f+l*l,x=_*p-h*y,b=(p*m-y*v)/x-r,w=(y*d-p*g)/x,M=(_*v-h*m)/x-i,T=(h*g-_*d)/x,N=w*w+T*T-1,k=2*(b*w+M*T+o),S=b*b+M*M-o*o,A=(-k-Math.sqrt(k*k-4*N*S))/(2*N);return{x:b+w*A+r,y:M+T*A+i,r:A}}function jo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s=a*a+c*c;if(s){var f=.5+((u*=u)-(o*=o))/(2*s),l=Math.sqrt(Math.max(0,2*o*(u+s)-(u-=s)*u-o*o))/(2*s);e.x=r+f*a+l*c,e.y=i+f*c-l*a}else e.x=r+u,e.y=i}function Ho(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i>e*e+r*r}function Xo(t,n,e){var r=t.x-n,i=t.y-e;return r*r+i*i}function Vo(t){this._=t,this.next=null,this.previous=null}function Wo(t){if(!(i=t.length))return 0;var n,e,r,i;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;jo(e,n,r=t[2]);var o,u,a,c,s,f,l,h=n.r*n.r,p=e.r*e.r,d=r.r*r.r,v=h+p+d,_=h*n.x+p*e.x+d*r.x,y=h*n.y+p*e.y+d*r.y;n=new Vo(n),e=new Vo(e),r=new Vo(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a=0;)n=i[o],n.z+=e,n.m+=e,e+=n.s+(r+=n.c)}function cu(t,n,e){return t.a.parent===n.parent?t.a:e}function su(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function fu(t){for(var n,e,r,i,o,u=new su(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new su(r[i],i)),e.parent=n;return(u.parent=new su(null,0)).children=[u],u}function lu(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y,g=[],m=n.children,x=0,b=m.length,w=n.value;xp&&(p=a),y=l*l*_,d=Math.max(p/y,y/h),d>v){l-=a;break}v=d}g.push(u={value:l,dice:s0)){if(o/=d,d<0){if(o0){if(o>p)return;o>h&&(h=o)}if(o=r-c,d||!(o<0)){if(o/=d,d<0){if(o>p)return;o>h&&(h=o)}else if(d>0){if(o0)){if(o/=v,v<0){if(o0){if(o>p)return;o>h&&(h=o)}if(o=i-s,v||!(o<0)){if(o/=v,v<0){if(o>p)return;o>h&&(h=o)}else if(v>0){if(o0||p<1)||(h>0&&(t[0]=[c+h*d,s+h*v]),p<1&&(t[1]=[c+p*d,s+p*v]),!0)}}}}}function Ru(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,f=t.right,l=s[0],h=s[1],p=f[0],d=f[1],v=(l+p)/2,_=(h+d)/2;if(d===h){if(v=r)return;if(l>p){if(c){if(c[1]>=i)return}else c=[v,e];o=[v,i]}else{if(c){if(c[1]1)if(l>p){if(c){if(c[1]>=i)return}else c=[(e-a)/u,e];o=[(i-a)/u,i]}else{if(c){if(c[1]=r)return}else c=[n,u*n+a];o=[r,u*r+a]}else{if(c){if(c[0]hm||Math.abs(i[0][1]-i[1][1])>hm)||delete sm[o]}function Du(t){return am[t.index]={site:t,halfedges:[]}}function Ou(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(e===r?(r=n[1],i=n[0]):(r=n[0],i=n[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function Fu(t,n){return n[+(n.left!==t.site)]}function Iu(t,n){return n[+(n.left===t.site)]}function Yu(){for(var t,n,e,r,i=0,o=am.length;ihm||Math.abs(v-h)>hm)&&(c.splice(a,0,sm.push(Pu(u,p,Math.abs(d-t)hm?[t,Math.abs(l-t)hm?[Math.abs(h-r)hm?[e,Math.abs(l-e)hm?[Math.abs(h-n)=-pm)){var p=c*c+s*s,d=f*f+l*l,v=(l*p-s*d)/h,_=(c*d-f*p)/h,y=fm.pop()||new ju;y.arc=t,y.site=i,y.x=v+u,y.y=(y.cy=_+a)+Math.sqrt(v*v+_*_),t.circle=y;for(var g=null,m=cm._;m;)if(y.yhm)a=a.L;else{if(i=o-Qu(a,u),!(i>hm)){r>-hm?(n=a.P,e=a):i>-hm?(n=a,e=a.N):n=e=a;break}if(!a.R){n=a;break}a=a.R}Du(t);var c=Wu(t);if(um.insert(n,c),n||e){if(n===e)return Xu(n),e=Wu(n.site),um.insert(c,e),c.edge=e.edge=zu(n.site,c.site),Hu(n),void Hu(e);if(!e)return void(c.edge=zu(n.site,c.site));Xu(n),Xu(e);var s=n.site,f=s[0],l=s[1],h=t[0]-f,p=t[1]-l,d=e.site,v=d[0]-f,_=d[1]-l,y=2*(h*_-p*v),g=h*h+p*p,m=v*v+_*_,x=[(_*g-p*m)/y+f,(h*m-v*g)/y+l];qu(e.edge,s,d,x),c.edge=zu(s,t,null,x),e.edge=zu(t,d,null,x),Hu(n),Hu(e)}}function Ju(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t.P;if(!u)return-(1/0);e=u.site;var a=e[0],c=e[1],s=c-n;if(!s)return a;var f=a-r,l=1/o-1/s,h=f/s;return l?(-h+Math.sqrt(h*h-2*l*(f*f/(-2*s)-c+s/2+i-o/2)))/l+r:(r+a)/2}function Qu(t,n){var e=t.N;if(e)return Ju(e,n);var r=t.site;return r[1]===n?r[0]:1/0}function Ku(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function ta(t,n){return n[1]-t[1]||n[0]-t[0]}function na(t,n){var e,r,i,o=t.sort(ta).pop();for(sm=[],am=new Array(t.length),um=new ku,cm=new ku;;)if(i=om,o&&(!i||o[1]Math.abs(t[1]-O[1])?M=!0:w=!0),O=t,b=!0,bm(),o()}function o(){var t;switch(m=O[0]-D[0],x=O[1]-D[1],k){case Mm:case wm:S&&(m=Math.max(P-l,Math.min(L-v,m)),h=l+m,_=v+m),A&&(x=Math.max(q-p,Math.min(R-y,x)),d=p+x,g=y+x);break;case Tm:S<0?(m=Math.max(P-l,Math.min(L-l,m)),h=l+m,_=v):S>0&&(m=Math.max(P-v,Math.min(L-v,m)),h=l,_=v+m),A<0?(x=Math.max(q-p,Math.min(R-p,x)),d=p+x,g=y):A>0&&(x=Math.max(q-y,Math.min(R-y,x)),d=p,g=y+x);break;case Nm:S&&(h=Math.max(P,Math.min(L,l-m*S)),_=Math.max(P,Math.min(L,v+m*S))),A&&(d=Math.max(q,Math.min(R,p-x*A)),g=Math.max(q,Math.min(R,y+x*A)))}_0&&(l=h-m),A<0?y=g-x:A>0&&(p=d-x),k=Mm,Y.attr("cursor",Em.selection),o());break;default:return}bm()}function s(){switch(t.event.keyCode){case 16:U&&(w=M=U=!1,o());break;case 18:k===Nm&&(S<0?v=_:S>0&&(l=h),A<0?y=g:A>0&&(p=d),k=Tm,o());break;case 32:k===Mm&&(t.event.altKey?(S&&(v=_-m*S,l=h+m*S),A&&(y=g-x*A,p=d+x*A),k=Nm):(S<0?v=_:S>0&&(l=h),A<0?y=g:A>0&&(p=d),k=Tm),Y.attr("cursor",Em[N]),o());break;default:return}bm()}if(t.event.touches){if(t.event.changedTouches.length1?0:t<-1?kx:Math.acos(t)}function Aa(t){return t>1?Sx:t<-1?-Sx:Math.asin(t)}function Ea(t){return(t=Ix(t/2))*t}function Ca(){}function za(t,n){t&&Xx.hasOwnProperty(t.type)&&Xx[t.type](t,n)}function Pa(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i=0?1:-1,i=r*e,o=Rx(n),u=Ix(n),a=Gm*u,c=Zm*o+a*Rx(i),s=a*r*Ix(i);Wx.add(Lx(s,c)),$m=t,Zm=o,Gm=u}function Oa(t){return[Lx(t[1],t[0]),Aa(t[2])]}function Fa(t){var n=t[0],e=t[1],r=Rx(e);return[r*Rx(n),r*Ix(n),Ix(e)]}function Ia(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Ya(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Ba(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function ja(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Ha(t){var n=Bx(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Xa(t,n){ox.push(ux=[Jm=t,Km=t]),ntx&&(tx=n)}function Va(t,n){var e=Fa([t*zx,n*zx]);if(ix){var r=Ya(ix,e),i=[r[1],-r[0],0],o=Ya(i,r);Ha(o),o=Oa(o);var u,a=t-nx,c=a>0?1:-1,s=o[0]*Cx*c,f=Px(a)>180;f^(c*nxtx&&(tx=u)):(s=(s+360)%360-180,f^(c*nxtx&&(tx=n))),f?tQa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t):Km>=Jm?(tKm&&(Km=t)):t>nx?Qa(Jm,t)>Qa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t)}else Xa(t,n);ix=e,nx=t}function Wa(){Qx.point=Va}function $a(){ux[0]=Jm,ux[1]=Km,Qx.point=Xa,ix=null}function Za(t,n){if(ix){var e=t-nx;Jx.add(Px(e)>180?e+(e>0?360:-360):e)}else ex=t,rx=n;Zx.point(t,n),Va(t,n)}function Ga(){Zx.lineStart()}function Ja(){Za(ex,rx),Zx.lineEnd(),Px(Jx)>Tx&&(Jm=-(Km=180)),ux[0]=Jm,ux[1]=Km,ix=null}function Qa(t,n){return(n-=t)<0?n+360:n}function Ka(t,n){return t[0]-n[0]}function tc(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nkx?t-Ex:t<-kx?t+Ex:t,n]}function hc(t,n,e){return(t%=Ex)?n||e?rb(dc(t),vc(n,e)):dc(t):n||e?vc(n,e):lc}function pc(t){return function(n,e){return n+=t,[n>kx?n-Ex:n<-kx?n+Ex:n,e]}}function dc(t){var n=pc(t);return n.invert=pc(-t),n}function vc(t,n){function e(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*r+a*i;return[Lx(c*o-f*u,a*r-s*i),Aa(f*o+c*u)]}var r=Rx(t),i=Ix(t),o=Rx(n),u=Ix(n);return e.invert=function(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*o-c*u;return[Lx(c*o+s*u,a*r+f*i),Aa(f*r-a*i)]},e}function _c(t,n,e,r,i,o){if(e){var u=Rx(n),a=Ix(n),c=r*e;null==i?(i=n+r*Ex,o=n-c/2):(i=yc(u,i),o=yc(u,o),(r>0?io)&&(i+=r*Ex));for(var s,f=i;r>0?f>o:f0){do s.point(0===f||3===f?t:e,f>1?r:n);while((f=(f+a+4)%4)!==l)}else s.point(o[0],o[1])}function u(r,i){return Px(r[0]-t)0?0:3:Px(r[0]-e)0?2:1:Px(r[1]-n)0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&k.point(t,n)}function s(){for(var n=0,e=0,i=_.length;er&&(l-o)*(r-u)>(h-u)*(t-o)&&++n:h<=r&&(l-o)*(r-u)<(h-u)*(t-o)&&--n;return n}function f(){k=S,v=[],_=[],N=!0}function l(){var t=s(),n=N&&t,e=(v=Js(v)).length;(n||e)&&(u.polygonStart(),n&&(u.lineStart(),o(null,null,1,u),u.lineEnd()),e&&xb(v,a,t,o,u),u.polygonEnd()),k=u,v=_=y=null}function h(){A.point=d,_&&_.push(y=[]),T=!0,M=!1,b=w=NaN}function p(){v&&(d(g,m),x&&M&&S.rejoin(),v.push(S.result())),A.point=c,M&&k.lineEnd()}function d(o,u){var a=i(o,u);if(_&&y.push([o,u]),T)g=o,m=u,x=a,T=!1,a&&(k.lineStart(),k.point(o,u));else if(a&&M)k.point(o,u);else{var c=[b=Math.max(wb,Math.min(bb,b)),w=Math.max(wb,Math.min(bb,w))],s=[o=Math.max(wb,Math.min(bb,o)),u=Math.max(wb,Math.min(bb,u))];gb(c,s,t,n,e,r)?(M||(k.lineStart(),k.point(c[0],c[1])),k.point(s[0],s[1]),a||k.lineEnd(),N=!1):a&&(k.lineStart(),k.point(o,u),N=!1)}b=o,w=u,M=a}var v,_,y,g,m,x,b,w,M,T,N,k=u,S=yb(),A={point:c,lineStart:h,lineEnd:p,polygonStart:f,polygonEnd:l};return A}}function bc(){Nb.point=Mc,Nb.lineEnd=wc}function wc(){Nb.point=Nb.lineEnd=Ca}function Mc(t,n){t*=zx,n*=zx,ib=t,ob=Ix(n),ub=Rx(n),Nb.point=Tc}function Tc(t,n){t*=zx,n*=zx;var e=Ix(n),r=Rx(n),i=Px(t-ib),o=Rx(i),u=Ix(i),a=r*u,c=ub*e-ob*r*o,s=ob*e+ub*r*o;Tb.add(Lx(Bx(a*a+c*c),s)),ib=t,ob=e,ub=r}function Nc(t,n,e){var r=Os(t,n-Tx,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function kc(t,n,e){var r=Os(t,n-Tx,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function Sc(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return Os(Ux(o/_)*_,i,_).map(h).concat(Os(Ux(s/y)*y,c,y).map(p)).concat(Os(Ux(r/d)*d,e,d).filter(function(t){return Px(t%_)>Tx}).map(f)).concat(Os(Ux(a/v)*v,u,v).filter(function(t){return Px(t%y)>Tx}).map(l))}var e,r,i,o,u,a,c,s,f,l,h,p,d=10,v=d,_=90,y=360,g=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[h(o).concat(p(c).slice(1),h(i).reverse().slice(1),p(s).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],s=+n[0][1],c=+n[1][1],o>i&&(n=o,o=i,i=n),s>c&&(n=s,s=c,c=n),t.precision(g)):[[o,s],[i,c]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],a=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),a>u&&(n=a,a=u,u=n),t.precision(g)):[[r,a],[e,u]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(_=+n[0],y=+n[1],t):[_,y]},t.stepMinor=function(n){return arguments.length?(d=+n[0],v=+n[1],t):[d,v]},t.precision=function(n){return arguments.length?(g=+n,f=Nc(a,u,90),l=kc(r,e,g),h=Nc(s,c,90),p=kc(o,i,g),t):g},t.extentMajor([[-180,-90+Tx],[180,90-Tx]]).extentMinor([[-180,-80-Tx],[180,80+Tx]])}function Ac(){return Sc()()}function Ec(){Lb.point=Cc}function Cc(t,n){Lb.point=zc,ab=sb=t,cb=fb=n}function zc(t,n){qb.add(fb*t-sb*n),sb=t,fb=n}function Pc(){zc(ab,cb)}function qc(t,n){tDb&&(Db=t),nOb&&(Ob=n)}function Lc(t,n){Ib+=t,Yb+=n,++Bb}function Rc(){Zb.point=Uc}function Uc(t,n){Zb.point=Dc,Lc(pb=t,db=n)}function Dc(t,n){var e=t-pb,r=n-db,i=Bx(e*e+r*r);jb+=i*(pb+t)/2,Hb+=i*(db+n)/2,Xb+=i,Lc(pb=t,db=n)}function Oc(){Zb.point=Lc}function Fc(){Zb.point=Yc}function Ic(){Bc(lb,hb)}function Yc(t,n){Zb.point=Bc,Lc(lb=pb=t,hb=db=n)}function Bc(t,n){var e=t-pb,r=n-db,i=Bx(e*e+r*r);jb+=i*(pb+t)/2,Hb+=i*(db+n)/2,Xb+=i,i=db*t-pb*n,Vb+=i*(pb+t),Wb+=i*(db+n),$b+=3*i,Lc(pb=t,db=n)}function jc(t){this._context=t}function Hc(){this._string=[]}function Xc(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Vc(t){return t.length>1}function Wc(t,n){return((t=t.x)[0]<0?t[1]-Sx-Tx:Sx-t[1])-((n=n.x)[0]<0?n[1]-Sx-Tx:Sx-n[1])}function $c(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,u){var a=o>0?kx:-kx,c=Px(o-e);Px(c-kx)0?Sx:-Sx),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),t.point(o,r),n=0):i!==a&&c>=kx&&(Px(e-i)Tx?qx((Ix(n)*(o=Rx(r))*Ix(e)-Ix(r)*(i=Rx(n))*Ix(t))/(i*o*u)):(n+r)/2}function Gc(t,n,e,r){var i;if(null==t)i=e*Sx,r.point(-kx,i),r.point(0,i),r.point(kx,i),r.point(kx,0),r.point(kx,-i),r.point(0,-i),r.point(-kx,-i),r.point(-kx,0),r.point(-kx,i);else if(Px(t[0]-n[0])>Tx){var o=t[0]4*n&&v--){var x=u+h,b=a+p,w=c+d,M=Bx(x*x+b*b+w*w),T=Aa(w/=M),N=Px(Px(w)-1)n||Px((y*E+g*C)/m-.5)>.3||u*h+a*p+c*d2?t[2]%360*zx:0,i()):[b*Cx,w*Cx,M*Cx]},n.precision=function(t){return arguments.length?(E=ow(r,A=t*t),o()):Bx(A)},n.fitExtent=function(t,e){return Kc(n,t,e)},n.fitSize=function(t,e){return ts(n,t,e)},function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,i()}}function os(t){var n=0,e=kx/3,r=is(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*zx,e=t[1]*zx):[n*Cx,e*Cx]},i}function us(t){function n(t,n){return[t*e,Ix(n)/e]}var e=Rx(t);return n.invert=function(t,n){return[t/e,Aa(n*e)]},n}function as(t,n){function e(t,n){var e=Bx(o-2*i*Ix(n))/i;return[e*Ix(t*=i),u-e*Rx(t)]}var r=Ix(t),i=(r+Ix(n))/2;if(Px(i)0?n<-Sx+Tx&&(n=-Sx+Tx):n>Sx-Tx&&(n=Sx-Tx);var e=o/Fx(ps(n),i);return[e*Ix(i*t),o-e*Rx(i*t)]}var r=Rx(t),i=t===n?Ix(t):Ox(r/Rx(n))/Ox(ps(n)/ps(t)),o=r*Fx(ps(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=Yx(i)*Bx(t*t+e*e);return[Lx(t,Px(e))/i*Yx(e),2*qx(Fx(o/r,1/i))-Sx]},e):ls}function vs(t,n){return[t,n]}function _s(t,n){function e(t,n){var e=o-n,r=i*t;return[e*Ix(r),o-e*Rx(r)]}var r=Rx(t),i=t===n?Ix(t):(r-Rx(n))/(n-t),o=r/i+t;return Px(i)n?1:t>=n?0:NaN},Ts=function(t){return 1===t.length&&(t=n(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r>>1;t(n[o],e)>0?i=o:r=o+1}return r}}},Ns=Ts(Ms),ks=Ns.right,Ss=Ns.left,As=function(t,n){return nt?1:n>=t?0:NaN},Es=function(t){return null===t?NaN:+t},Cs=function(t,n){var e,r,i=t.length,o=0,u=0,a=-1,c=0;if(null==n)for(;++a1)return u/(c-1)},zs=function(t,n){var e=Cs(t,n);return e?Math.sqrt(e):e},Ps=function(t,n){var e,r,i,o=-1,u=t.length;if(null==n){for(;++o=r){e=i=r;break}for(;++or&&(e=r),i=r){e=i=r;break}for(;++or&&(e=r),i=f;)l.pop(),--h;var p,d=new Array(h+1);for(i=0;i<=h;++i)p=d[i]=[],p.x0=i>0?l[i-1]:s,p.x1=i=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,o=Math.floor(i),u=+e(t[o],o,t),a=+e(t[o+1],o+1,t);return u+(a-u)*(i-o)}},Vs=function(t,n,e){return t=Rs.call(t,Es).sort(Ms),Math.ceil((e-n)/(2*(Xs(t,.75)-Xs(t,.25))*Math.pow(t.length,-1/3)))},Ws=function(t,n,e){return Math.ceil((e-n)/(3.5*zs(t)*Math.pow(t.length,-1/3)))},$s=function(t,n){var e,r,i=-1,o=t.length;if(null==n){for(;++i=r){e=r;break}for(;++ie&&(e=r)}else{for(;++i=r){e=r;break}for(;++ie&&(e=r)}return e},Zs=function(t,n){var e,r=0,i=t.length,o=-1,u=i;if(null==n)for(;++o=0;)for(r=t[i],n=r.length;--n>=0;)e[--u]=r[n];return e},Qs=function(t,n){var e,r,i=-1,o=t.length;if(null==n){for(;++i=r){e=r;break}for(;++ir&&(e=r)}else{for(;++i=r){e=r;break}for(;++ir&&(e=r)}return e},Ks=function(t){for(var n=0,e=t.length-1,r=t[0],i=new Array(e<0?0:e);n=f.length)return null!=r?r(n):null!=e?n.sort(e):n;for(var c,s,l,h=-1,p=n.length,d=f[i++],v=o(),_=u();++hf.length)return t;var i,o=l[e-1];return null!=r&&e>=f.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=o?i.sort(function(t,n){return o(t.key,n.key)}):i}var e,r,i,f=[],l=[];return i={object:function(n){return t(n,0,u,a)},map:function(n){return t(n,0,c,s)},entries:function(e){return n(t(e,0,c,s),0)},key:function(t){return f.push(t),i},sortKeys:function(t){return l[f.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}},sf=o.prototype;f.prototype=l.prototype={constructor:f,has:sf.has,add:function(t){return t+="",this[af+t]=t,this},remove:sf.remove,clear:sf.clear,values:sf.keys,size:sf.size,empty:sf.empty,each:sf.each};var ff=function(t){var n=[];for(var e in t)n.push(e);return n},lf=function(t){var n=[];for(var e in t)n.push(t[e]);return n},hf=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},pf=function(t,n){return t=null==t?0:+t,n=null==n?1:+n,1===arguments.length?(n=t,t=0):n-=t,function(){return Math.random()*n+t}},df=function(t,n){var e,r;return t=null==t?0:+t,n=null==n?1:+n,function(){var i;if(null!=e)i=e,e=null;else do e=2*Math.random()-1,i=2*Math.random()-1,r=e*e+i*i;while(!r||r>1);return t+n*i*Math.sqrt(-2*Math.log(r)/r)}},vf=function(){var t=df.apply(this,arguments);return function(){return Math.exp(t())}},_f=function(t){return function(){for(var n=0,e=0;e=0;--n)s.push(t[r[o[n]][2]]);for(n=+a;na!=s>a&&u<(c-e)*(a-r)/(s-r)+e&&(f=!f),c=e,s=r;return f},Gf=function(t){for(var n,e,r=-1,i=t.length,o=t[i-1],u=o[0],a=o[1],c=0;++rKf)if(Math.abs(f*a-c*s)>Kf&&i){var h=e-o,p=r-u,d=a*a+c*c,v=h*h+p*p,_=Math.sqrt(d),y=Math.sqrt(l),g=i*Math.tan((Jf-Math.acos((d+l-v)/(2*_*y)))/2),m=g/y,x=g/_;Math.abs(m-1)>Kf&&this._.push("L",t+m*s,",",n+m*f),this._.push("A",i,",",i,",0,0,",+(f*h>s*p),",",this._x1=t+x*a,",",this._y1=n+x*c)}else this._.push("L",this._x1=t,",",this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n,e=+e;var u=e*Math.cos(r),a=e*Math.sin(r),c=t+u,s=n+a,f=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._.push("M",c,",",s):(Math.abs(this._x1-c)>Kf||Math.abs(this._y1-s)>Kf)&&this._.push("L",c,",",s),e&&(l>tl?this._.push("A",e,",",e,",0,1,",f,",",t-u,",",n-a,"A",e,",",e,",0,1,",f,",",this._x1=c,",",this._y1=s):(l<0&&(l=l%Qf+Qf),this._.push("A",e,",",e,",0,",+(l>=Jf),",",f,",",this._x1=t+e*Math.cos(i),",",this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._.push("M",this._x0=this._x1=+t,",",this._y0=this._y1=+n,"h",+e,"v",+r,"h",-e,"Z")},toString:function(){return this._.join("")}};var nl=function(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return R(this.cover(n,e),n,e,t)},el=function(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var e=this._x0,r=this._y0,i=this._x1,o=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1;else{if(!(e>t||t>i||r>n||n>o))return this;var u,a,c=i-e,s=this._root;switch(a=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do u=new Array(4),u[a]=s,s=u;while(c*=2,i=e+c,o=r+c,t>i||n>o);break;case 1:do u=new Array(4),u[a]=s,s=u;while(c*=2,e=i-c,o=r+c,e>t||n>o);break;case 2:do u=new Array(4),u[a]=s,s=u;while(c*=2,i=e+c,r=o-c,t>i||r>n);break;case 3:do u=new Array(4),u[a]=s,s=u;while(c*=2,e=i-c,r=o-c,e>t||r>n)}this._root&&this._root.length&&(this._root=s)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this},rl=function(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t},il=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},ol=function(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i},ul=function(t,n,e){var r,i,o,u,a,c,s,f=this._x0,l=this._y0,h=this._x1,p=this._y1,d=[],v=this._root;for(v&&d.push(new ol(v,f,l,h,p)),null==e?e=1/0:(f=t-e,l=n-e,h=t+e,p=n+e,e*=e);c=d.pop();)if(!(!(v=c.node)||(i=c.x0)>h||(o=c.y0)>p||(u=c.x1)=y)<<1|t>=_)&&(c=d[d.length-1],d[d.length-1]=d[d.length-1-s],d[d.length-1-s]=c)}else{var g=t-+this._x.call(null,v.data),m=n-+this._y.call(null,v.data),x=g*g+m*m;if(x=(a=(d+_)/2))?d=a:_=a,(f=u>=(c=(v+y)/2))?v=c:y=c,n=p,!(p=p[l=f<<1|s]))return this;if(!p.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;p.data!==t;)if(r=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(p=n[0]||n[1]||n[2]||n[3])&&p===(n[3]||n[2]||n[1]||n[0])&&!p.length&&(e?e[h]=p:this._root=p),this):(this._root=i,this)},cl=function(){return this._root},sl=function(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t},fl=function(t){var n,e,r,i,o,u,a=[],c=this._root;for(c&&a.push(new ol(c,this._x0,this._y0,this._x1,this._y1));n=a.pop();)if(!t(c=n.node,r=n.x0,i=n.y0,o=n.x1,u=n.y1)&&c.length){var s=(r+o)/2,f=(i+u)/2;(e=c[3])&&a.push(new ol(e,s,f,o,u)),(e=c[2])&&a.push(new ol(e,r,f,s,u)),(e=c[1])&&a.push(new ol(e,s,i,o,f)),(e=c[0])&&a.push(new ol(e,r,i,s,f))}return this},ll=function(t){var n,e=[],r=[];for(this._root&&e.push(new ol(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var i=n.node;if(i.length){var o,u=n.x0,a=n.y0,c=n.x1,s=n.y1,f=(u+c)/2,l=(a+s)/2;(o=i[0])&&e.push(new ol(o,u,a,f,l)),(o=i[1])&&e.push(new ol(o,f,a,c,l)),(o=i[2])&&e.push(new ol(o,u,l,f,s)),(o=i[3])&&e.push(new ol(o,f,l,c,s))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this},hl=function(t){return arguments.length?(this._x=t,this):this._x},pl=function(t){return arguments.length?(this._y=t,this):this._y},dl=I.prototype=Y.prototype;dl.copy=function(){var t,n,e=new Y(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=B(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=B(n));return e},dl.add=nl,dl.addAll=U,dl.cover=el,dl.data=rl,dl.extent=il,dl.find=ul,dl.remove=al,dl.removeAll=D,dl.root=cl,dl.size=sl,dl.visit=fl,dl.visitAfter=ll,dl.x=hl,dl.y=pl;var vl=[].slice,_l={};j.prototype=Z.prototype={constructor:j,defer:function(t){if("function"!=typeof t||this._call)throw new Error;if(null!=this._error)return this;var n=vl.call(arguments,1);return n.push(t),++this._waiting,this._tasks.push(n),H(this),this},abort:function(){return null==this._error&&W(this,new Error("abort")),this},await:function(t){if("function"!=typeof t||this._call)throw new Error;return this._call=function(n,e){t.apply(null,[n].concat(e))},$(this),this},awaitAll:function(t){if("function"!=typeof t||this._call)throw new Error;return this._call=t,$(this),this}};var yl=function(t){ +return function(){return t}},gl=1e-12,ml=Math.PI,xl=ml/2,bl=2*ml,wl=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-xl,p=u.apply(this,arguments)-xl,d=Math.abs(p-h),v=p>h;if(c||(c=t=L()),lgl)if(d>bl-gl)c.moveTo(l*Math.cos(h),l*Math.sin(h)),c.arc(0,0,l,h,p,!v),f>gl&&(c.moveTo(f*Math.cos(p),f*Math.sin(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,N=T>gl&&(i?+i.apply(this,arguments):Math.sqrt(f*f+l*l)),k=Math.min(Math.abs(l-f)/2,+r.apply(this,arguments)),S=k,A=k;if(N>gl){var E=nt(N/f*Math.sin(T)),C=nt(N/l*Math.sin(T));(w-=2*E)>gl?(E*=v?1:-1,x+=E,b-=E):(w=0,x=b=(h+p)/2),(M-=2*C)>gl?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*Math.cos(g),P=l*Math.sin(g),q=f*Math.cos(b),R=f*Math.sin(b);if(k>gl){var U=l*Math.cos(m),D=l*Math.sin(m),O=f*Math.cos(x),F=f*Math.sin(x);if(dgl?et(z,P,O,F,U,D,q,R):[q,R],Y=z-I[0],B=P-I[1],j=U-I[0],H=D-I[1],X=1/Math.sin(Math.acos((Y*j+B*H)/(Math.sqrt(Y*Y+B*B)*Math.sqrt(j*j+H*H)))/2),V=Math.sqrt(I[0]*I[0]+I[1]*I[1]);S=Math.min(k,(f-V)/(X-1)),A=Math.min(k,(l-V)/(X+1))}}M>gl?A>gl?(_=rt(O,F,z,P,l,A,v),y=rt(U,D,q,R,l,A,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),Agl&&w>gl?S>gl?(_=rt(q,R,U,D,f,-S,v),y=rt(z,P,O,F,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return Tl().defined(u).curve(c).context(a)}var e=ot,r=null,i=yl(0),o=ut,u=yl(!0),a=null,c=Ml,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:yl(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:yl(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:yl(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:yl(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(u="function"==typeof n?n:yl(!!n),t):u},t.curve=function(n){return arguments.length?(c=n,null!=a&&(s=c(a)),t):c},t.context=function(n){return arguments.length?(null==n?a=s=null:s=c(a=n),t):a},t},kl=function(t,n){return nt?1:n>=t?0:NaN},Sl=function(t){return t},Al=function(){function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h),_=+i.apply(this,arguments),y=Math.min(bl,Math.max(-bl,o.apply(this,arguments)-_)),g=Math.min(Math.abs(y)/h,u.apply(this,arguments)),m=g*(y<0?-1:1);for(a=0;a0&&(p+=l);for(null!=e?d.sort(function(t,n){return e(v[t],v[n])}):null!=r&&d.sort(function(n,e){return r(t[n],t[e])}),a=0,s=p?(y-h*m)/p:0;a0?l*s:0)+m,v[c]={data:t[c],index:a,value:l,startAngle:_,endAngle:f,padAngle:g};return v}var n=Sl,e=kl,r=null,i=yl(0),o=yl(bl),u=yl(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:yl(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:yl(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:yl(+n),t):o},t.padAngle=function(n){return arguments.length?(u="function"==typeof n?n:yl(+n),t):u},t},El=ct(Ml);at.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var Cl=function(){return st(Tl().curve(El))},zl=function(){var t=Nl().curve(El),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return st(e())},delete t.lineX0,t.lineEndAngle=function(){return st(r())},delete t.lineX1,t.lineInnerRadius=function(){return st(i())},delete t.lineY0,t.lineOuterRadius=function(){return st(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(ct(t)):n()._curve},t},Pl={draw:function(t,n){var e=Math.sqrt(n/ml);t.moveTo(e,0),t.arc(0,0,e,0,bl)}},ql={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},Ll=Math.sqrt(1/3),Rl=2*Ll,Ul={draw:function(t,n){var e=Math.sqrt(n/Rl),r=e*Ll;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},Dl=.8908130915292852,Ol=Math.sin(ml/10)/Math.sin(7*ml/10),Fl=Math.sin(bl/10)*Ol,Il=-Math.cos(bl/10)*Ol,Yl={draw:function(t,n){var e=Math.sqrt(n*Dl),r=Fl*e,i=Il*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var u=bl*o/5,a=Math.cos(u),c=Math.sin(u);t.lineTo(c*e,-a*e),t.lineTo(a*r-c*i,c*r+a*i)}t.closePath()}},Bl={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},jl=Math.sqrt(3),Hl={draw:function(t,n){var e=-Math.sqrt(n/(3*jl));t.moveTo(0,2*e),t.lineTo(-jl*e,-e),t.lineTo(jl*e,-e),t.closePath()}},Xl=-.5,Vl=Math.sqrt(3)/2,Wl=1/Math.sqrt(12),$l=3*(Wl/2+1),Zl={draw:function(t,n){var e=Math.sqrt(n/$l),r=e/2,i=e*Wl,o=r,u=e*Wl+e,a=-o,c=u;t.moveTo(r,i),t.lineTo(o,u),t.lineTo(a,c),t.lineTo(Xl*r-Vl*i,Vl*r+Xl*i),t.lineTo(Xl*o-Vl*u,Vl*o+Xl*u),t.lineTo(Xl*a-Vl*c,Vl*a+Xl*c),t.lineTo(Xl*r+Vl*i,Xl*i-Vl*r),t.lineTo(Xl*o+Vl*u,Xl*u-Vl*o),t.lineTo(Xl*a+Vl*c,Xl*c-Vl*a),t.closePath()}},Gl=[Pl,ql,Ul,Bl,Yl,Hl,Zl],Jl=function(){function t(){var t;if(r||(r=t=L()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=yl(Pl),e=yl(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:yl(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t},Ql=function(){};lt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:ft(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:ft(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};var Kl=function(t){return new lt(t)};ht.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:ft(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};var th=function(t){return new ht(t)};pt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:ft(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}};var nh=function(t){return new pt(t)};dt.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],u=t[e]-i,a=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*u),this._beta*n[c]+(1-this._beta)*(o+r*a));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var eh=function t(n){function e(t){return 1===n?new lt(t):new dt(t,n)}return e.beta=function(n){return t(+n)},e}(.85);_t.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:vt(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:vt(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var rh=function t(n){function e(t){return new _t(t,n)}return e.tension=function(n){return t(+n)},e}(0);yt.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:vt(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var ih=function t(n){function e(t){return new yt(t,n)}return e.tension=function(n){return t(+n)},e}(0);gt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:vt(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var oh=function t(n){function e(t){return new gt(t,n)}return e.tension=function(n){return t(+n)},e}(0);xt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:mt(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var uh=function t(n){function e(t){return n?new xt(t,n):new _t(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);bt.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:mt(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var ah=function t(n){function e(t){return n?new bt(t,n):new yt(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);wt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:mt(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var ch=function t(n){function e(t){return n?new wt(t,n):new gt(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Mt.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}};var sh=function(t){return new Mt(t)};At.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:St(this,this._t0,kt(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,St(this,kt(this,e=Nt(this,t,n)),e);break;default:St(this,this._t0,e=Nt(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(Et.prototype=Object.create(At.prototype)).point=function(t,n){At.prototype.point.call(this,n,t)},Ct.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},qt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=Lt(t),i=Lt(n),o=0,u=1;u=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var lh=function(t){return new Rt(t,.5)},hh=Array.prototype.slice,ph=function(t,n){if((r=t.length)>1)for(var e,r,i=1,o=t[n[0]],u=o.length;i=0;)e[n]=n;return e},vh=function(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o0){for(var e,r,i,o=0,u=t[0].length;o0){for(var e,r=0,i=t[n[0]],o=i.length;r0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u=240?t-240:t+120,i,r),Qt(t,i,r),Qt(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var Rh=Math.PI/180,Uh=180/Math.PI,Dh=18,Oh=.95047,Fh=1,Ih=1.08883,Yh=4/29,Bh=6/29,jh=3*Bh*Bh,Hh=Bh*Bh*Bh;Mh(nn,tn,It(Yt,{brighter:function(t){return new nn(this.l+Dh*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new nn(this.l-Dh*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return t=Fh*rn(t),n=Oh*rn(n),e=Ih*rn(e),new Wt(on(3.2404542*n-1.5371385*t-.4985314*e),on(-.969266*n+1.8760108*t+.041556*e),on(.0556434*n-.2040259*t+1.0572252*e),this.opacity)}})),Mh(sn,cn,It(Yt,{brighter:function(t){return new sn(this.h,this.c,this.l+Dh*(null==t?1:t),this.opacity)},darker:function(t){return new sn(this.h,this.c,this.l-Dh*(null==t?1:t),this.opacity)},rgb:function(){return Kt(this).rgb()}}));var Xh=-.14861,Vh=1.78277,Wh=-.29227,$h=-.90649,Zh=1.97294,Gh=Zh*$h,Jh=Zh*Vh,Qh=Vh*Wh-$h*Xh;Mh(hn,ln,It(Yt,{brighter:function(t){return t=null==t?Nh:Math.pow(Nh,t),new hn(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Th:Math.pow(Th,t),new hn(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*Rh,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new Wt(255*(n+e*(Xh*r+Vh*i)),255*(n+e*(Wh*r+$h*i)),255*(n+e*(Zh*r)),this.opacity)}}));var Kh,tp,np,ep,rp=function(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=ro&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:lp(e,r)})),o=dp.lastIndex;return o0)for(var e,r,i=new Array(e),o=0;o=s)return u;if(i)return i=!1,o;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++=200&&e<300||304===e){if(u)try{n=u.call(r,f)}catch(t){return void c.call("error",r,t)}else n=f;c.call("load",r,n)}else c.call("error",r,t)}var r,i,u,a,c=Pn("beforesend","progress","load","error"),s=o(),f=new XMLHttpRequest,l=null,h=null,p=0;if("undefined"==typeof XDomainRequest||"withCredentials"in f||!/^(http(s)?:)?\/\//.test(t)||(f=new XDomainRequest),"onload"in f?f.onload=f.onerror=f.ontimeout=e:f.onreadystatechange=function(t){f.readyState>3&&e(t)},f.onprogress=function(t){c.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?s.get(t):(null==n?s.remove(t):s.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(a=t,r):a},timeout:function(t){return arguments.length?(p=+t,r):p},user:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},password:function(t){return arguments.length<1?h:(h=null==t?null:t+"",r)},response:function(t){return u=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return f.open(n,t,!0,l,h),null==i||s.has("accept")||s.set("accept",i+",*/*"),f.setRequestHeader&&s.each(function(t,n){f.setRequestHeader(n,t)}),null!=i&&f.overrideMimeType&&f.overrideMimeType(i),null!=a&&(f.responseType=a),p>0&&(f.timeout=p),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=In(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),c.call("beforesend",r,f),f.send(null==e?null:e),r},abort:function(){return f.abort(),r},on:function(){var t=c.on.apply(c,arguments);return t===c?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},Gp=function(t,n){return function(e,r){var i=Zp(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},Jp=Gp("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),Qp=Gp("application/json",function(t){return JSON.parse(t.responseText)}),Kp=Gp("text/plain",function(t){return t.responseText}),td=Gp("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),nd=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=Zp(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Bn(n,r=t)):r},o.row(r),i?o.get(i):o}},ed=nd("text/csv",Ip),rd=nd("text/tab-separated-values",Xp),id=0,od=0,ud=0,ad=1e3,cd=0,sd=0,fd=0,ld="object"==typeof performance&&performance.now?performance:Date,hd="function"==typeof requestAnimationFrame?requestAnimationFrame:function(t){setTimeout(t,17)};Xn.prototype=Vn.prototype={constructor:Xn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?jn():+e)+(null==n?0:+n),this._next||Dp===this||(Dp?Dp._next=this:Up=this,Dp=this),this._call=t,this._time=e,Jn()},stop:function(){this._call&&(this._call=null,this._time=1/0,Jn())}};var pd=function(t,n,e){var r=new Xn;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r},dd=function(t,n,e){var r=new Xn,i=n;return null==n?(r.restart(t,n,e),r):(n=+n,e=null==e?jn():+e,r.restart(function o(u){u+=i,r.restart(o,i+=n,e),t(u)},n,e),r)},vd=new Date,_d=new Date,yd=Qn(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});yd.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Qn(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):yd:null};var gd=yd.range,md=1e3,xd=6e4,bd=36e5,wd=864e5,Md=6048e5,Td=Qn(function(t){t.setTime(Math.floor(t/md)*md)},function(t,n){t.setTime(+t+n*md)},function(t,n){return(n-t)/md},function(t){return t.getUTCSeconds()}),Nd=Td.range,kd=Qn(function(t){t.setTime(Math.floor(t/xd)*xd)},function(t,n){t.setTime(+t+n*xd)},function(t,n){return(n-t)/xd},function(t){return t.getMinutes()}),Sd=kd.range,Ad=Qn(function(t){var n=t.getTimezoneOffset()*xd%bd;n<0&&(n+=bd),t.setTime(Math.floor((+t-n)/bd)*bd+n)},function(t,n){t.setTime(+t+n*bd)},function(t,n){return(n-t)/bd},function(t){return t.getHours()}),Ed=Ad.range,Cd=Qn(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*xd)/wd},function(t){return t.getDate()-1}),zd=Cd.range,Pd=Kn(0),qd=Kn(1),Ld=Kn(2),Rd=Kn(3),Ud=Kn(4),Dd=Kn(5),Od=Kn(6),Fd=Pd.range,Id=qd.range,Yd=Ld.range,Bd=Rd.range,jd=Ud.range,Hd=Dd.range,Xd=Od.range,Vd=Qn(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),Wd=Vd.range,$d=Qn(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});$d.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Qn(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var Zd=$d.range,Gd=Qn(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*xd)},function(t,n){return(n-t)/xd},function(t){return t.getUTCMinutes()}),Jd=Gd.range,Qd=Qn(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+n*bd)},function(t,n){return(n-t)/bd},function(t){return t.getUTCHours()}),Kd=Qd.range,tv=Qn(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/wd},function(t){return t.getUTCDate()-1}),nv=tv.range,ev=te(0),rv=te(1),iv=te(2),ov=te(3),uv=te(4),av=te(5),cv=te(6),sv=ev.range,fv=rv.range,lv=iv.range,hv=ov.range,pv=uv.range,dv=av.range,vv=cv.range,_v=Qn(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),yv=_v.range,gv=Qn(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});gv.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Qn(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var mv,xv=gv.range,bv=function(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]},wv=function(t){return t=bv(Math.abs(t)),t?t[1]:NaN},Mv=function(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}},Tv=function(t,n){t=t.toPrecision(n);t:for(var e,r=t.length,i=1,o=-1;i0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},Nv=function(t,n){var e=bv(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(mv=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+bv(t,Math.max(0,n+o-1))[0]},kv=function(t,n){var e=bv(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")},Sv={"":Tv,"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return kv(100*t,n)},r:kv,s:Nv,X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},Av=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i,Ev=function(t){return new ne(t)};ne.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var Cv,zv=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"],Pv=function(t){function n(t){function n(t){var n,i,c,g=d,m=v;if("c"===p)m=_(t)+m,t="";else{t=+t;var x=(t<0||1/t<0)&&(t*=-1,!0);if(t=_(t,h),x)for(n=-1,i=t.length,x=!1;++nc||c>57){m=(46===c?o+t.slice(n+1):t.slice(n))+m,t=t.slice(0,n);break}}l&&!s&&(t=r(t,1/0));var b=g.length+t.length+m.length,w=b>1)+g+t+m+w.slice(b)}return w+g+t+m}t=Ev(t);var e=t.fill,u=t.align,a=t.sign,c=t.symbol,s=t.zero,f=t.width,l=t.comma,h=t.precision,p=t.type,d="$"===c?i[0]:"#"===c&&/[boxX]/.test(p)?"0"+p.toLowerCase():"",v="$"===c?i[1]:/[%p]/.test(p)?"%":"",_=Sv[p],y=!p||/[defgprs%]/.test(p);return h=null==h?p?6:12:/[gprs]/.test(p)?Math.max(1,Math.min(21,h)):Math.max(0,Math.min(20,h)),n.toString=function(){return t+""},n}function e(t,e){var r=n((t=Ev(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(wv(e)/3))),o=Math.pow(10,-i),u=zv[8+i/3];return function(t){return r(o*t)+u}}var r=t.grouping&&t.thousands?Mv(t.grouping,t.thousands):ee,i=t.currency,o=t.decimal;return{format:n,formatPrefix:e}};re({decimal:".",thousands:",",grouping:[3],currency:["$",""]});var qv,Lv=function(t){return Math.max(0,-wv(Math.abs(t)))},Rv=function(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(wv(n)/3)))-wv(Math.abs(t)))},Uv=function(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,wv(n)-wv(t))+1},Dv={"-":"",_:" ",0:"0"},Ov=/^\s*\d+/,Fv=/^%/,Iv=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;nr({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Yv="%Y-%m-%dT%H:%M:%S.%LZ",Bv=Date.prototype.toISOString?er:t.utcFormat(Yv),jv=+new Date("2000-01-01T00:00:00.000Z")?rr:t.utcParse(Yv),Hv=Array.prototype,Xv=Hv.map,Vv=Hv.slice,Wv={name:"implicit"},$v=function(t){return function(){return t}},Zv=function(t){return+t},Gv=[0,1],Jv=function(n,r,i){var o,u=n[0],a=n[n.length-1],c=e(u,a,null==r?10:r);switch(i=Ev(null==i?",f":i),i.type){case"s":var s=Math.max(Math.abs(u),Math.abs(a));return null!=i.precision||isNaN(o=Rv(c,s))||(i.precision=o),t.formatPrefix(i,s);case"":case"e":case"g":case"p":case"r":null!=i.precision||isNaN(o=Uv(c,Math.max(Math.abs(u),Math.abs(a))))||(i.precision=o-("e"===i.type));break;case"f":case"%":null!=i.precision||isNaN(o=Lv(c))||(i.precision=o-2*("%"===i.type))}return t.format(i)},Qv=function(t,n){t=t.slice();var e,r=0,i=t.length-1,o=t[r],u=t[i];return u1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return __.h=360*t-100,__.s=1.5-1.5*n,__.l=.8-.9*n,__+""},g_=Lr(c_("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),m_=Lr(c_("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),x_=Lr(c_("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),b_=Lr(c_("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),w_="http://www.w3.org/1999/xhtml",M_={svg:"http://www.w3.org/2000/svg",xhtml:w_,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},T_=function(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),M_.hasOwnProperty(n)?{space:M_[n],local:t}:t},N_=function(t){var n=T_(t);return(n.local?Dr:Ur)(n)},k_=0;Fr.prototype=Or.prototype={constructor:Fr,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var S_=function(t){return function(){return this.matches(t)}};if("undefined"!=typeof document){var A_=document.documentElement;if(!A_.matches){var E_=A_.webkitMatchesSelector||A_.msMatchesSelector||A_.mozMatchesSelector||A_.oMatchesSelector;S_=function(t){return function(){return E_.call(this,t)}}}}var C_=S_,z_={};if(t.event=null,"undefined"!=typeof document){var P_=document.documentElement;"onmouseenter"in P_||(z_={mouseenter:"mouseover",mouseleave:"mouseout"})}var q_=function(t,n,e){var r,i,o=Br(t+""),u=o.length;{if(!(arguments.length<2)){for(a=n?Hr:jr,null==e&&(e=!1),r=0;r=b&&(b=x+1);!(m=_[b])&&++b=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this},G_=function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=Jr);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?ii:"function"==typeof n?ui:oi)(t,n,null==e?"":e)):iy(r=this.node()).getComputedStyle(r,null).getPropertyValue(t)},uy=function(t,n){return arguments.length>1?this.each((null==n?ai:"function"==typeof n?si:ci)(t,n)):this.node()[t]};hi.prototype={add:function(t){var n=this._names.indexOf(t);n<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var ay=function(t,n){var e=fi(t+"");if(arguments.length<2){for(var r=li(this.node()),i=-1,o=e.length;++iky&&e.stateNy&&e.name===n)return new so([[t]],rg,n,+r)}return null},og=Array.prototype.slice,ug=function(t){return t},ag=1,cg=2,sg=3,fg=4,lg=1e-6,hg=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=To(e),t.y=ko(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=Ao(t),c=Eo(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Mo,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},pg=function(t){var n,e,r,i,o=this,u=[o];do for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r=0;--e)i.push(n[e]);return this},vg=function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e=0;)e+=r[i].value;n.value=e})},yg=function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},gg=function(t){for(var n=this,e=Co(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},mg=function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},xg=function(){var t=[];return this.each(function(n){t.push(n)}),t},bg=function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},wg=function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n};Uo.prototype=zo.prototype={constructor:Uo,each:pg,eachAfter:vg,eachBefore:dg,sum:_g,sort:yg,path:gg,ancestors:mg,descendants:xg,leaves:bg,links:wg,copy:Po};var Mg=function(t){for(var n,e=(t=t.slice()).length,r=null,i=r;e;){var o=new Do(t[e-1]);i=i?i.next=o:r=o,t[n]=t[--e]}return{head:r,tail:i}},Tg=function(t){return Fo(Mg(t),[])},Ng=function(t){return Wo(t),t},kg=function(t){return function(){return t}},Sg=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Qo(n)).eachAfter(Ko(i,.5)).eachBefore(tu(1)):t.eachBefore(Qo(Jo)).eachAfter(Ko(Go,1)).eachAfter(Ko(i,t.r/Math.min(e,r))).eachBefore(tu(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=Go;return t.radius=function(e){return arguments.length?(n=$o(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:kg(+n),t):i},t},Ag=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},Eg=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a0)throw new Error("cycle");return o}var n=nu,e=eu;return t.id=function(e){return arguments.length?(n=Zo(e),t):n},t.parentId=function(n){return arguments.length?(e=Zo(n),t):e},t};su.prototype=Object.create(Uo.prototype);var Rg=function(){function t(t){var r=fu(t);if(r.eachAfter(n),r.parent.m=-r.z,r.eachBefore(e),c)t.eachBefore(i);else{var s=t,f=t,l=t;t.eachBefore(function(t){t.xf.x&&(f=t),t.depth>l.depth&&(l=t)});var h=s===f?1:o(s,f)/2,p=h-s.x,d=u/(f.x+h+p),v=a/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,i=t.i?e[t.i-1]:null;if(n){au(t);var u=(n[0].z+n[n.length-1].z)/2;i?(t.z=i.z+o(t._,i._),t.m=t.z-u):t.z=u}else i&&(t.z=i.z+o(t._,i._));t.parent.A=r(t,i,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t,n,e){if(n){for(var r,i=t,u=t,a=n,c=i.parent.children[0],s=i.m,f=u.m,l=a.m,h=c.m;a=ou(a),i=iu(i),a&&i;)c=iu(c),u=ou(u),u.a=t,r=a.z+l-i.z-s+o(a._,i._),r>0&&(uu(cu(a,t,e),t,r),s+=r,f+=r),l+=a.m,s+=i.m,h+=c.m,f+=u.m;a&&!ou(u)&&(u.t=a,u.m+=l-f),i&&!iu(c)&&(c.t=i,c.m+=s-h,e=t)}return e}function i(t){t.x*=u,t.y=t.depth*a}var o=ru,u=1,a=1,c=null;return t.separation=function(n){return arguments.length?(o=n,t):o},t.size=function(n){return arguments.length?(c=!1,u=+n[0],a=+n[1],t):c?null:[u,a]},t.nodeSize=function(n){return arguments.length?(c=!0,u=+n[0],a=+n[1],t):c?[u,a]:null},t},Ug=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a1?n:1)},e}(Dg),Fg=function(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&t.eachBefore(Ag),t}function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x1=u,s.y1=a,void 0}for(var l=f[t],h=e/2+l,p=t+1,d=n-1;p>>1;f[v]u-r){var g=(i*y+a*_)/e;o(t,p,_,r,i,u,g),o(p,n,y,r,g,u,a)}else{var m=(r*y+u*_)/e;o(t,p,_,r,i,m,a),o(p,n,y,m,i,u,a)}}var u,a,c=t.children,s=c.length,f=new Array(s+1);for(f[0]=a=u=0;u1?n:1)},e}(Dg),jg=function(t,n){function e(){var e,i,o=r.length,u=0,a=0;for(e=0;es+d||if+d||on){var v=s-a.x-a.vx,_=f-a.y-a.vy,y=v*v+_*_;yt.r&&(t.r=t[n].r)}function r(){if(i){var n,e=i.length;for(o=new Array(e),n=0;n1?(null==n?h.remove(t):h.set(t,i(n)),u):h.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s1?(d.on(t,n),u):d.on(t)}}},Jg=function(){function t(t){var n,a=i.length,c=I(i,_u,yu).visitAfter(e);for(u=t,n=0;n=f)){(t.data!==o||t.next)&&(0===i&&(i=Xg(),p+=i*i),0===c&&(c=Xg(),p+=c*c),p0?gy(this).transition().duration(N).call(u,f,a):gy(this).call(n.transform,f)}}function h(){if(y.apply(this,arguments)){var n,e,r,i=a(this,arguments),o=t.event.changedTouches,u=o.length;for(oa(),n=0;n0?1:t<0?-1:0; +},Bx=Math.sqrt,jx=Math.tan,Hx={Feature:function(t,n){za(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++rTx?tx=90:Jx<-Tx&&(Qm=-90),ux[0]=Jm,ux[1]=Km}},Kx=function(t){var n,e,r,i,o,u,a;if(tx=Km=-(Jm=Qm=1/0),ox=[],Vx(t,Qx),e=ox.length){for(ox.sort(Ka),n=1,r=ox[0],o=[r];nQa(r[0],r[1])&&(r[1]=i[1]),Qa(i[0],r[1])>Qa(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-(1/0),e=o.length-1,n=0,r=o[e];n<=e;r=i,++n)i=o[n],(a=Qa(r[1],i[0]))>u&&(u=a,Jm=i[0],Km=r[1])}return ox=ux=null,Jm===1/0||Qm===1/0?[[NaN,NaN],[NaN,NaN]]:[[Jm,Qm],[Km,tx]]},tb={sphere:Ca,point:nc,lineStart:rc,lineEnd:uc,polygonStart:function(){tb.lineStart=ac,tb.lineEnd=cc},polygonEnd:function(){tb.lineStart=rc,tb.lineEnd=uc}},nb=function(t){ax=cx=sx=fx=lx=hx=px=dx=vx=_x=yx=0,Vx(t,tb);var n=vx,e=_x,r=yx,i=n*n+e*e+r*r;return i2?t[2]*zx:0),n.invert=function(n){return n=t.invert(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n},n},_b=function(){function t(t,n){e.push(t=r(t,n)),t[0]*=Cx,t[1]*=Cx}function n(){var t=i.apply(this,arguments),n=o.apply(this,arguments)*zx,c=u.apply(this,arguments)*zx;return e=[],r=hc(-t[0]*zx,-t[1]*zx,0).invert,_c(a,n,c,1),t={type:"Polygon",coordinates:[e]},e=r=null,t}var e,r,i=eb([0,0]),o=eb(90),u=eb(6),a={point:t};return n.center=function(t){return arguments.length?(i="function"==typeof t?t:eb([+t[0],+t[1]]),n):i},n.radius=function(t){return arguments.length?(o="function"==typeof t?t:eb(+t),n):o},n.precision=function(t){return arguments.length?(u="function"==typeof t?t:eb(+t),n):u},n},yb=function(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:Ca,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}},gb=function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=n[0],f=n[1],l=0,h=1,p=s-a,d=f-c;if(u=e-a,p||!(u>0)){if(u/=p,p<0){if(u0){if(u>h)return;u>l&&(l=u)}if(u=i-a,p||!(u<0)){if(u/=p,p<0){if(u>h)return;u>l&&(l=u)}else if(p>0){if(u0)){if(u/=d,d<0){if(u0){if(u>h)return;u>l&&(l=u)}if(u=o-c,d||!(u<0)){if(u/=d,d<0){if(u>h)return;u>l&&(l=u)}else if(d>0){if(u0&&(t[0]=a+l*p,t[1]=c+l*d),h<1&&(n[0]=a+h*p,n[1]=c+h*d),!0}}}}},mb=function(t,n){return Px(t[0]-n[0])=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}h=h.o,s=h.z,p=!p}while(!h.v);i.lineEnd()}}},bb=1e9,wb=-bb,Mb=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=xc(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][1],o=+a[1][0],u=+a[1][1],t=n=null,e):[[r,i],[o,u]]}}},Tb=Xm(),Nb={sphere:Ca,point:Ca,lineStart:bc,lineEnd:Ca,polygonStart:Ca,polygonEnd:Ca},kb=function(t){return Tb.reset(),Vx(t,Nb),+Tb},Sb=[null,null],Ab={type:"LineString",coordinates:Sb},Eb=function(t,n){return Sb[0]=t,Sb[1]=n,kb(Ab)},Cb=function(t,n){var e=t[0]*zx,r=t[1]*zx,i=n[0]*zx,o=n[1]*zx,u=Rx(r),a=Ix(r),c=Rx(o),s=Ix(o),f=u*Rx(e),l=u*Ix(e),h=c*Rx(i),p=c*Ix(i),d=2*Aa(Bx(Ea(o-r)+u*c*Ea(i-e))),v=Ix(d),_=d?function(t){var n=Ix(t*=d)/v,e=Ix(d-t)/v,r=e*f+n*h,i=e*l+n*p,o=e*a+n*s;return[Lx(i,r)*Cx,Lx(o,Bx(r*r+i*i))*Cx]}:function(){return[e*Cx,r*Cx]};return _.distance=d,_},zb=function(t){return t},Pb=Xm(),qb=Xm(),Lb={point:Ca,lineStart:Ca,lineEnd:Ca,polygonStart:function(){Lb.lineStart=Ec,Lb.lineEnd=Pc},polygonEnd:function(){Lb.lineStart=Lb.lineEnd=Lb.point=Ca,Pb.add(Px(qb)),qb.reset()},result:function(){var t=Pb/2;return Pb.reset(),t}},Rb=1/0,Ub=Rb,Db=-Rb,Ob=Db,Fb={point:qc,lineStart:Ca,lineEnd:Ca,polygonStart:Ca,polygonEnd:Ca,result:function(){var t=[[Rb,Ub],[Db,Ob]];return Db=Ob=-(Ub=Rb=1/0),t}},Ib=0,Yb=0,Bb=0,jb=0,Hb=0,Xb=0,Vb=0,Wb=0,$b=0,Zb={point:Lc,lineStart:Rc,lineEnd:Oc,polygonStart:function(){Zb.lineStart=Fc,Zb.lineEnd=Ic},polygonEnd:function(){Zb.point=Lc,Zb.lineStart=Rc,Zb.lineEnd=Oc},result:function(){var t=$b?[Vb/$b,Wb/$b]:Xb?[jb/Xb,Hb/Xb]:Bb?[Ib/Bb,Yb/Bb]:[NaN,NaN];return Ib=Yb=Bb=jb=Hb=Xb=Vb=Wb=$b=0,t}};jc.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,Ex)}},result:Ca},Hc.prototype={_circle:Xc(4.5),pointRadius:function(t){return this._circle=Xc(t),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._string.push("M",t,",",n),this._point=1;break;case 1:this._string.push("L",t,",",n);break;default:this._string.push("M",t,",",n,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}}};var Gb=function(t,n){function e(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),Vx(t,r(i))),i.result()}var r,i,o=4.5;return e.area=function(t){return Vx(t,r(Lb)),Lb.result()},e.bounds=function(t){return Vx(t,r(Fb)),Fb.result()},e.centroid=function(t){return Vx(t,r(Zb)),Zb.result()},e.projection=function(n){return arguments.length?(r=null==(t=n)?zb:n.stream,e):t},e.context=function(t){return arguments.length?(i=null==(n=t)?new Hc:new jc(t),"function"!=typeof o&&i.pointRadius(o),e):n},e.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),e):o},e.projection(t).context(n)},Jb=Xm(),Qb=function(t,n){var e=n[0],r=n[1],i=[Ix(e),-Rx(e),0],o=0,u=0;Jb.reset();for(var a=0,c=t.length;a=0?1:-1,T=M*w,N=T>kx,k=d*x;if(Jb.add(Lx(k*M*Ix(T),v*b+k*Rx(T))),o+=N?w+M*Ex:w,N^h>=e^g>=e){var S=Ya(Fa(l),Fa(y));Ha(S);var A=Ya(i,S);Ha(A);var E=(N^w>=0?-1:1)*Aa(A[2]);(r>E||r===E&&(S[0]||S[1]))&&(u+=N^w>=0?1:-1)}}return(o<-Tx||o0){for(x||(o.polygonStart(),x=!0),o.lineStart(),t=0;t1&&2&i&&u.push(u.pop().concat(u.shift())),d.push(u.filter(Vc))}var p,d,v,_=n(o),y=i.invert(r[0],r[1]),g=yb(),m=n(g),x=!1,b={point:u,lineStart:c,lineEnd:s,polygonStart:function(){b.point=f,b.lineStart=l,b.lineEnd=h,d=[],p=[]},polygonEnd:function(){b.point=u,b.lineStart=c,b.lineEnd=s,d=Js(d);var t=Qb(p,y);d.length?(x||(o.polygonStart(),x=!0),xb(d,Wc,t,e,o)):t&&(x||(o.polygonStart(),x=!0),o.lineStart(),e(null,null,1,o),o.lineEnd()),x&&(o.polygonEnd(),x=!1),d=p=null},sphere:function(){o.polygonStart(),o.lineStart(),e(null,null,1,o),o.lineEnd(),o.polygonEnd()}};return b}},tw=Kb(function(){return!0},$c,Gc,[-kx,-Sx]),nw=function(t,n){function e(e,r,i,o){_c(o,t,n,i,e,r)}function r(t,n){return Rx(t)*Rx(n)>a}function i(t){var n,e,i,a,f;return{lineStart:function(){a=i=!1,f=1},point:function(l,h){var p,d=[l,h],v=r(l,h),_=c?v?0:u(l,h):v?u(l+(l<0?kx:-kx),h):0;if(!n&&(a=i=v)&&t.lineStart(),v!==i&&(p=o(n,d),(mb(n,p)||mb(d,p))&&(d[0]+=Tx,d[1]+=Tx,v=r(d[0],d[1]))),v!==i)f=0,v?(t.lineStart(),p=o(d,n),t.point(p[0],p[1])):(p=o(n,d),t.point(p[0],p[1]),t.lineEnd()),n=p;else if(s&&n&&c^v){var y;_&e||!(y=o(d,n,!0))||(f=0,c?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1])))}!v||n&&mb(n,d)||t.point(d[0],d[1]),n=d,i=v,e=_},lineEnd:function(){i&&t.lineEnd(),n=null},clean:function(){return f|(a&&i)<<1}}}function o(t,n,e){var r=Fa(t),i=Fa(n),o=[1,0,0],u=Ya(r,i),c=Ia(u,u),s=u[0],f=c-s*s;if(!f)return!e&&t;var l=a*c/f,h=-a*s/f,p=Ya(o,u),d=ja(o,l),v=ja(u,h);Ba(d,v);var _=p,y=Ia(d,_),g=Ia(_,_),m=y*y-g*(Ia(d,d)-1);if(!(m<0)){var x=Bx(m),b=ja(_,(-y-x)/g);if(Ba(b,d),b=Oa(b),!e)return b;var w,M=t[0],T=n[0],N=t[1],k=n[1];T0^b[1]<(Px(b[0]-M)kx^(M<=b[0]&&b[0]<=T)){var C=ja(_,(-y+x)/g);return Ba(C,d),[b,Oa(C)]}}}function u(n,e){var r=c?t:kx-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var a=Rx(t),c=a>0,s=Px(a)>Tx;return Kb(r,i,e,c?[0,-t]:[-kx,t-kx])},ew=function(t){return{stream:Jc(t)}};Qc.prototype={constructor:Qc,point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var rw=16,iw=Rx(30*zx),ow=function(t,n){return+n?es(t,n):ns(t)},uw=Jc({point:function(t,n){this.stream.point(t*zx,n*zx)}}),aw=function(){return os(as).scale(155.424).center([0,33.6442])},cw=function(){return aw().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])},sw=function(){function t(t){var n=t[0],e=t[1];return a=null,i.point(n,e),a||(o.point(n,e),a)||(u.point(n,e),a)}function n(){return e=r=null,t}var e,r,i,o,u,a,c=cw(),s=aw().rotate([154,0]).center([-2,58.5]).parallels([55,65]),f=aw().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,n){a=[t,n]}};return t.invert=function(t){var n=c.scale(),e=c.translate(),r=(t[0]-e[0])/n,i=(t[1]-e[1])/n;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?f:c).invert(t)},t.stream=function(t){return e&&r===t?e:e=cs([c.stream(r=t),s.stream(t),f.stream(t)])},t.precision=function(t){return arguments.length?(c.precision(t),s.precision(t),f.precision(t),n()):c.precision()},t.scale=function(n){return arguments.length?(c.scale(n),s.scale(.35*n),f.scale(n),t.translate(c.translate())):c.scale()},t.translate=function(t){if(!arguments.length)return c.translate();var e=c.scale(),r=+t[0],a=+t[1];return i=c.translate(t).clipExtent([[r-.455*e,a-.238*e],[r+.455*e,a+.238*e]]).stream(l),o=s.translate([r-.307*e,a+.201*e]).clipExtent([[r-.425*e+Tx,a+.12*e+Tx],[r-.214*e-Tx,a+.234*e-Tx]]).stream(l),u=f.translate([r-.205*e,a+.212*e]).clipExtent([[r-.214*e+Tx,a+.166*e+Tx],[r-.115*e-Tx,a+.234*e-Tx]]).stream(l),n()},t.fitExtent=function(n,e){return Kc(t,n,e)},t.fitSize=function(n,e){return ts(t,n,e)},t.scale(1070)},fw=ss(function(t){return Bx(2/(1+t))});fw.invert=fs(function(t){return 2*Aa(t/2)});var lw=function(){return rs(fw).scale(124.75).clipAngle(179.999)},hw=ss(function(t){return(t=Sa(t))&&t/Ix(t)});hw.invert=fs(function(t){return t});var pw=function(){return rs(hw).scale(79.4188).clipAngle(179.999)};ls.invert=function(t,n){return[t,2*qx(Dx(n))-Sx]};var dw=function(){return hs(ls).scale(961/Ex)},vw=function(){return os(ds).scale(109.5).parallels([30,30])};vs.invert=vs;var _w=function(){return rs(vs).scale(152.63)},yw=function(){return os(_s).scale(131.154).center([0,13.9389])};ys.invert=fs(qx);var gw=function(){return rs(ys).scale(144.049).clipAngle(60)},mw=function(){function t(){return i=o=null,u}var n,e,r,i,o,u,a=1,c=0,s=0,f=zb,l=null,h=zb;return u={stream:function(t){return i&&o===t?i:i=f(h(o=t))},clipExtent:function(i){return arguments.length?(h=null==i?(l=n=e=r=null,zb):xc(l=+i[0][0],n=+i[0][1],e=+i[1][0],r=+i[1][1]),t()):null==l?null:[[l,n],[e,r]]},scale:function(n){return arguments.length?(f=gs(a=+n,c,s),t()):a},translate:function(n){return arguments.length?(f=gs(a,c=+n[0],s=+n[1]),t()):[c,s]},fitExtent:function(t,n){return Kc(u,t,n)},fitSize:function(t,n){return ts(u,t,n)}}};ms.invert=fs(Aa);var xw=function(){return rs(ms).scale(249.5).clipAngle(90+Tx)};xs.invert=fs(function(t){return 2*qx(t)});var bw=function(){return rs(xs).scale(250).clipAngle(142)};bs.invert=function(t,n){return[-n,2*qx(Dx(t))-Sx]};var ww=function(){var t=hs(bs),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):(t=n(),[t[1],-t[0]])},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90]).scale(159.155)};t.version=ws,t.bisect=ks,t.bisectRight=ks,t.bisectLeft=Ss,t.ascending=Ms,t.bisector=Ts,t.descending=As,t.deviation=zs,t.extent=Ps,t.histogram=Hs,t.thresholdFreedmanDiaconis=Vs,t.thresholdScott=Ws,t.thresholdSturges=js,t.max=$s,t.mean=Zs,t.median=Gs,t.merge=Js,t.min=Qs,t.pairs=Ks,t.permute=tf,t.quantile=Xs,t.range=Os,t.scan=nf,t.shuffle=ef,t.sum=rf,t.ticks=Bs,t.tickStep=e,t.transpose=of,t.variance=Cs,t.zip=uf,t.entries=hf,t.keys=ff,t.values=lf,t.map=o,t.set=l,t.nest=cf,t.randomUniform=pf,t.randomNormal=df,t.randomLogNormal=vf,t.randomBates=yf,t.randomIrwinHall=_f,t.randomExponential=gf,t.easeLinear=h,t.easeQuad=v,t.easeQuadIn=p,t.easeQuadOut=d,t.easeQuadInOut=v,t.easeCubic=g,t.easeCubicIn=_,t.easeCubicOut=y,t.easeCubicInOut=g,t.easePoly=wf,t.easePolyIn=xf,t.easePolyOut=bf,t.easePolyInOut=wf,t.easeSin=b,t.easeSinIn=m,t.easeSinOut=x,t.easeSinInOut=b,t.easeExp=T,t.easeExpIn=w,t.easeExpOut=M,t.easeExpInOut=T,t.easeCircle=S,t.easeCircleIn=N,t.easeCircleOut=k,t.easeCircleInOut=S,t.easeBounce=E,t.easeBounceIn=A,t.easeBounceOut=E,t.easeBounceInOut=C,t.easeBack=Of,t.easeBackIn=Uf,t.easeBackOut=Df,t.easeBackInOut=Of,t.easeElastic=jf,t.easeElasticIn=Bf,t.easeElasticOut=jf,t.easeElasticInOut=Hf,t.polygonArea=Xf,t.polygonCentroid=Vf,t.polygonHull=$f,t.polygonContains=Zf,t.polygonLength=Gf,t.path=L,t.quadtree=I,t.queue=Z,t.arc=wl,t.area=Nl,t.line=Tl,t.pie=Al,t.radialArea=zl,t.radialLine=Cl,t.symbol=Jl,t.symbols=Gl,t.symbolCircle=Pl,t.symbolCross=ql,t.symbolDiamond=Ul,t.symbolSquare=Bl,t.symbolStar=Yl,t.symbolTriangle=Hl,t.symbolWye=Zl,t.curveBasisClosed=th,t.curveBasisOpen=nh,t.curveBasis=Kl,t.curveBundle=eh,t.curveCardinalClosed=ih,t.curveCardinalOpen=oh,t.curveCardinal=rh,t.curveCatmullRomClosed=ah,t.curveCatmullRomOpen=ch,t.curveCatmullRom=uh,t.curveLinearClosed=sh,t.curveLinear=Ml,t.curveMonotoneX=zt,t.curveMonotoneY=Pt,t.curveNatural=fh,t.curveStep=lh,t.curveStepAfter=Dt,t.curveStepBefore=Ut,t.stack=vh,t.stackOffsetExpand=_h,t.stackOffsetNone=ph,t.stackOffsetSilhouette=yh,t.stackOffsetWiggle=gh,t.stackOrderAscending=mh,t.stackOrderDescending=xh,t.stackOrderInsideOut=bh,t.stackOrderNone=dh,t.stackOrderReverse=wh,t.color=Bt,t.rgb=Vt,t.hsl=Gt,t.lab=tn,t.hcl=cn,t.cubehelix=ln,t.interpolate=_p,t.interpolateArray=sp,t.interpolateDate=fp,t.interpolateNumber=lp,t.interpolateObject=hp,t.interpolateRound=yp,t.interpolateString=vp,t.interpolateTransformCss=bp,t.interpolateTransformSvg=wp,t.interpolateZoom=Sp,t.interpolateRgb=up,t.interpolateRgbBasis=ap,t.interpolateRgbBasisClosed=cp,t.interpolateHsl=Ap,t.interpolateHslLong=Ep,t.interpolateLab=En,t.interpolateHcl=Cp,t.interpolateHclLong=zp,t.interpolateCubehelix=Pp,t.interpolateCubehelixLong=qp,t.interpolateBasis=rp,t.interpolateBasisClosed=ip,t.quantize=Lp,t.dispatch=Pn,t.dsvFormat=Op,t.csvParse=Ip,t.csvParseRows=Yp,t.csvFormat=Bp,t.csvFormatRows=jp,t.tsvParse=Xp,t.tsvParseRows=Vp,t.tsvFormat=Wp,t.tsvFormatRows=$p,t.request=Zp,t.html=Jp,t.json=Qp,t.text=Kp,t.xml=td,t.csv=ed,t.tsv=rd,t.now=jn,t.timer=Vn,t.timerFlush=Wn,t.timeout=pd,t.interval=dd,t.timeInterval=Qn,t.timeMillisecond=yd,t.timeMilliseconds=gd,t.timeSecond=Td,t.timeSeconds=Nd,t.timeMinute=kd,t.timeMinutes=Sd,t.timeHour=Ad,t.timeHours=Ed,t.timeDay=Cd,t.timeDays=zd,t.timeWeek=Pd,t.timeWeeks=Fd,t.timeSunday=Pd,t.timeSundays=Fd,t.timeMonday=qd,t.timeMondays=Id,t.timeTuesday=Ld,t.timeTuesdays=Yd;t.timeWednesday=Rd;t.timeWednesdays=Bd,t.timeThursday=Ud,t.timeThursdays=jd,t.timeFriday=Dd,t.timeFridays=Hd,t.timeSaturday=Od,t.timeSaturdays=Xd,t.timeMonth=Vd,t.timeMonths=Wd,t.timeYear=$d,t.timeYears=Zd,t.utcMillisecond=yd,t.utcMilliseconds=gd,t.utcSecond=Td,t.utcSeconds=Nd,t.utcMinute=Gd,t.utcMinutes=Jd,t.utcHour=Qd,t.utcHours=Kd,t.utcDay=tv,t.utcDays=nv,t.utcWeek=ev,t.utcWeeks=sv,t.utcSunday=ev,t.utcSundays=sv,t.utcMonday=rv,t.utcMondays=fv,t.utcTuesday=iv,t.utcTuesdays=lv,t.utcWednesday=ov,t.utcWednesdays=hv,t.utcThursday=uv,t.utcThursdays=pv,t.utcFriday=av,t.utcFridays=dv,t.utcSaturday=cv,t.utcSaturdays=vv,t.utcMonth=_v,t.utcMonths=yv,t.utcYear=gv,t.utcYears=xv,t.formatLocale=Pv,t.formatDefaultLocale=re,t.formatSpecifier=Ev,t.precisionFixed=Lv,t.precisionPrefix=Rv,t.precisionRound=Uv,t.isoFormat=Bv,t.isoParse=jv,t.timeFormatLocale=ae,t.timeFormatDefaultLocale=nr,t.scaleBand=or,t.scalePoint=ar,t.scaleIdentity=yr,t.scaleLinear=_r,t.scaleLog=Tr,t.scaleOrdinal=ir,t.scaleImplicit=Wv,t.scalePow=kr,t.scaleSqrt=Sr,t.scaleQuantile=Ar,t.scaleQuantize=Er,t.scaleThreshold=Cr,t.scaleTime=u_,t.scaleUtc=a_,t.schemeCategory10=s_,t.schemeCategory20b=f_,t.schemeCategory20c=l_,t.schemeCategory20=h_,t.scaleSequential=Rr,t.interpolateCubehelixDefault=p_,t.interpolateRainbow=y_,t.interpolateWarm=d_,t.interpolateCool=v_,t.interpolateViridis=g_,t.interpolateMagma=m_,t.interpolateInferno=x_,t.interpolatePlasma=b_,t.creator=N_,t.customEvent=Xr,t.local=Or,t.matcher=C_,t.mouse=U_,t.namespace=T_,t.namespaces=M_,t.select=gy,t.selectAll=my,t.selection=Pi,t.selector=D_,t.selectorAll=F_,t.touch=xy,t.touches=by,t.window=iy,t.active=ig,t.interrupt=Py,t.transition=fo,t.axisTop=mo,t.axisRight=xo,t.axisBottom=bo,t.axisLeft=wo,t.cluster=hg,t.hierarchy=zo,t.pack=Sg,t.packSiblings=Ng,t.packEnclose=Tg,t.partition=Cg,t.stratify=Lg,t.tree=Rg,t.treemap=Fg,t.treemapBinary=Ig,t.treemapDice=Eg,t.treemapSlice=Ug,t.treemapSliceDice=Yg,t.treemapSquarify=Og,t.treemapResquarify=Bg,t.forceCenter=jg,t.forceCollide=Vg,t.forceLink=Wg,t.forceManyBody=Jg,t.forceSimulation=Gg,t.forceX=Qg,t.forceY=Kg,t.drag=rm,t.dragDisable=nm,t.dragEnable=mu,t.voronoi=dm,t.zoom=gm,t.zoomIdentity=_m,t.zoomTransform=ia,t.brush=Lm,t.brushX=_a,t.brushY=ya,t.brushSelection=va,t.chord=Ym,t.ribbon=Hm,t.geoAlbers=cw,t.geoAlbersUsa=sw,t.geoArea=Gx,t.geoAzimuthalEqualArea=lw,t.geoAzimuthalEqualAreaRaw=fw,t.geoAzimuthalEquidistant=pw,t.geoAzimuthalEquidistantRaw=hw,t.geoBounds=Kx,t.geoCentroid=nb,t.geoCircle=_b,t.geoClipExtent=Mb,t.geoConicConformal=vw,t.geoConicConformalRaw=ds,t.geoConicEqualArea=aw,t.geoConicEqualAreaRaw=as,t.geoConicEquidistant=yw,t.geoConicEquidistantRaw=_s,t.geoDistance=Eb,t.geoEquirectangular=_w,t.geoEquirectangularRaw=vs,t.geoGnomonic=gw,t.geoGnomonicRaw=ys,t.geoGraticule=Sc,t.geoGraticule10=Ac,t.geoIdentity=mw,t.geoInterpolate=Cb,t.geoLength=kb,t.geoMercator=dw,t.geoMercatorRaw=ls,t.geoOrthographic=xw,t.geoOrthographicRaw=ms,t.geoPath=Gb,t.geoProjection=rs,t.geoProjectionMutator=is,t.geoRotation=vb,t.geoStereographic=bw,t.geoStereographicRaw=xs,t.geoStream=Vx,t.geoTransform=ew,t.geoTransverseMercator=ww,t.geoTransverseMercatorRaw=bs,Object.defineProperty(t,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/examples/js/lib/intercom.js b/examples/js/lib/intercom.js new file mode 100644 index 0000000..ac61ecd --- /dev/null +++ b/examples/js/lib/intercom.js @@ -0,0 +1,413 @@ +/*! intercom.js | https://github.com/diy/intercom.js | Apache License (v2) */ + +var Intercom = (function() { + + // --- lib/events.js --- + + var EventEmitter = function() {}; + + EventEmitter.createInterface = function(space) { + var methods = {}; + + methods.on = function(name, fn) { + if (typeof this[space] === 'undefined') { + this[space] = {}; + } + if (!this[space].hasOwnProperty(name)) { + this[space][name] = []; + } + this[space][name].push(fn); + }; + + methods.off = function(name, fn) { + if (typeof this[space] === 'undefined') return; + if (this[space].hasOwnProperty(name)) { + util.removeItem(fn, this[space][name]); + } + }; + + methods.trigger = function(name) { + if (typeof this[space] !== 'undefined' && this[space].hasOwnProperty(name)) { + var args = Array.prototype.slice.call(arguments, 1); + for (var i = 0; i < this[space][name].length; i++) { + this[space][name][i].apply(this[space][name][i], args); + } + } + }; + + return methods; + }; + + var pvt = EventEmitter.createInterface('_handlers'); + EventEmitter.prototype._on = pvt.on; + EventEmitter.prototype._off = pvt.off; + EventEmitter.prototype._trigger = pvt.trigger; + + var pub = EventEmitter.createInterface('handlers'); + EventEmitter.prototype.on = function() { + pub.on.apply(this, arguments); + Array.prototype.unshift.call(arguments, 'on'); + this._trigger.apply(this, arguments); + }; + EventEmitter.prototype.off = pub.off; + EventEmitter.prototype.trigger = pub.trigger; + + // --- lib/localstorage.js --- + + var localStorage = window.localStorage; + if (typeof localStorage === 'undefined') { + localStorage = { + getItem : function() {}, + setItem : function() {}, + removeItem : function() {} + }; + } + + // --- lib/util.js --- + + var util = {}; + + util.guid = (function() { + var S4 = function() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + }; + return function() { + return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4(); + }; + })(); + + util.throttle = function(delay, fn) { + var last = 0; + return function() { + var now = (new Date()).getTime(); + if (now - last > delay) { + last = now; + fn.apply(this, arguments); + } + }; + }; + + util.extend = function(a, b) { + if (typeof a === 'undefined' || !a) { a = {}; } + if (typeof b === 'object') { + for (var key in b) { + if (b.hasOwnProperty(key)) { + a[key] = b[key]; + } + } + } + return a; + }; + + util.removeItem = function(item, array) { + for (var i = array.length - 1; i >= 0; i--) { + if (array[i] === item) { + array.splice(i, 1); + } + } + return array; + }; + + // --- lib/intercom.js --- + + /** + * A cross-window broadcast service built on top + * of the HTML5 localStorage API. The interface + * mimic socket.io in design. + * + * @author Brian Reavis + * @constructor + */ + + var Intercom = function() { + var self = this; + var now = (new Date()).getTime(); + + this.origin = util.guid(); + this.lastMessage = now; + this.bindings = []; + this.receivedIDs = {}; + this.previousValues = {}; + + var storageHandler = function() { self._onStorageEvent.apply(self, arguments); }; + if (window.attachEvent) { document.attachEvent('onstorage', storageHandler); } + else { window.addEventListener('storage', storageHandler, false); }; + }; + + Intercom.prototype._transaction = function(fn) { + var TIMEOUT = 1000; + var WAIT = 20; + + var self = this; + var executed = false; + var listening = false; + var waitTimer = null; + + var lock = function() { + if (executed) return; + + var now = (new Date()).getTime(); + var activeLock = parseInt(localStorage.getItem(INDEX_LOCK) || 0); + if (activeLock && now - activeLock < TIMEOUT) { + if (!listening) { + self._on('storage', lock); + listening = true; + } + waitTimer = window.setTimeout(lock, WAIT); + return; + } + executed = true; + localStorage.setItem(INDEX_LOCK, now); + + fn(); + unlock(); + }; + + var unlock = function() { + if (listening) { self._off('storage', lock); } + if (waitTimer) { window.clearTimeout(waitTimer); } + localStorage.removeItem(INDEX_LOCK); + }; + + lock(); + }; + + Intercom.prototype._cleanup_emit = util.throttle(100, function() { + var self = this; + + this._transaction(function() { + var now = (new Date()).getTime(); + var threshold = now - THRESHOLD_TTL_EMIT; + var changed = 0; + + var messages = JSON.parse(localStorage.getItem(INDEX_EMIT) || '[]'); + for (var i = messages.length - 1; i >= 0; i--) { + if (messages[i].timestamp < threshold) { + messages.splice(i, 1); + changed++; + } + } + if (changed > 0) { + localStorage.setItem(INDEX_EMIT, JSON.stringify(messages)); + } + }); + }); + + Intercom.prototype._cleanup_once = util.throttle(100, function() { + var self = this; + + this._transaction(function() { + var timestamp, ttl, key; + var table = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}'); + var now = (new Date()).getTime(); + var changed = 0; + + for (key in table) { + if (self._once_expired(key, table)) { + delete table[key]; + changed++; + } + } + + if (changed > 0) { + localStorage.setItem(INDEX_ONCE, JSON.stringify(table)); + } + }); + }); + + Intercom.prototype._once_expired = function(key, table) { + if (!table) return true; + if (!table.hasOwnProperty(key)) return true; + if (typeof table[key] !== 'object') return true; + var ttl = table[key].ttl || THRESHOLD_TTL_ONCE; + var now = (new Date()).getTime(); + var timestamp = table[key].timestamp; + return timestamp < now - ttl; + }; + + Intercom.prototype._localStorageChanged = function(event, field) { + if (event && event.key) { + return event.key === field; + } + + var currentValue = localStorage.getItem(field); + if (currentValue === this.previousValues[field]) { + return false; + } + this.previousValues[field] = currentValue; + return true; + }; + + Intercom.prototype._onStorageEvent = function(event) { + event = event || window.event; + var self = this; + + if (this._localStorageChanged(event, INDEX_EMIT)) { + this._transaction(function() { + var now = (new Date()).getTime(); + var data = localStorage.getItem(INDEX_EMIT); + var messages = JSON.parse(data || '[]'); + for (var i = 0; i < messages.length; i++) { + if (messages[i].origin === self.origin) continue; + if (messages[i].timestamp < self.lastMessage) continue; + if (messages[i].id) { + if (self.receivedIDs.hasOwnProperty(messages[i].id)) continue; + self.receivedIDs[messages[i].id] = true; + } + self.trigger(messages[i].name, messages[i].payload); + } + self.lastMessage = now; + }); + } + + this._trigger('storage', event); + }; + + Intercom.prototype._emit = function(name, message, id) { + id = (typeof id === 'string' || typeof id === 'number') ? String(id) : null; + if (id && id.length) { + if (this.receivedIDs.hasOwnProperty(id)) return; + this.receivedIDs[id] = true; + } + + var packet = { + id : id, + name : name, + origin : this.origin, + timestamp : (new Date()).getTime(), + payload : message + }; + + var self = this; + this._transaction(function() { + var data = localStorage.getItem(INDEX_EMIT) || '[]'; + var delimiter = (data === '[]') ? '' : ','; + data = [data.substring(0, data.length - 1), delimiter, JSON.stringify(packet), ']'].join(''); + localStorage.setItem(INDEX_EMIT, data); + self.trigger(name, message); + + window.setTimeout(function() { self._cleanup_emit(); }, 50); + }); + }; + + Intercom.prototype.bind = function(object, options) { + for (var i = 0; i < Intercom.bindings.length; i++) { + var binding = Intercom.bindings[i].factory(object, options || null, this); + if (binding) { this.bindings.push(binding); } + } + }; + + Intercom.prototype.emit = function(name, message) { + this._emit.apply(this, arguments); + this._trigger('emit', name, message); + }; + + Intercom.prototype.once = function(key, fn, ttl) { + if (!Intercom.supported) return; + + var self = this; + this._transaction(function() { + var data = JSON.parse(localStorage.getItem(INDEX_ONCE) || '{}'); + if (!self._once_expired(key, data)) return; + + data[key] = {}; + data[key].timestamp = (new Date()).getTime(); + if (typeof ttl === 'number') { + data[key].ttl = ttl * 1000; + } + + localStorage.setItem(INDEX_ONCE, JSON.stringify(data)); + fn(); + + window.setTimeout(function() { self._cleanup_once(); }, 50); + }); + }; + + util.extend(Intercom.prototype, EventEmitter.prototype); + + Intercom.bindings = []; + Intercom.supported = (typeof localStorage !== 'undefined'); + + var INDEX_EMIT = 'intercom'; + var INDEX_ONCE = 'intercom_once'; + var INDEX_LOCK = 'intercom_lock'; + + var THRESHOLD_TTL_EMIT = 50000; + var THRESHOLD_TTL_ONCE = 1000 * 3600; + + Intercom.destroy = function() { + localStorage.removeItem(INDEX_LOCK); + localStorage.removeItem(INDEX_EMIT); + localStorage.removeItem(INDEX_ONCE); + }; + + Intercom.getInstance = (function() { + var intercom = null; + return function() { + if (!intercom) { + intercom = new Intercom(); + } + return intercom; + }; + })(); + + // --- lib/bindings/socket.js --- + + /** + * Socket.io binding for intercom.js. + * + * - When a message is received on the socket, it's emitted on intercom. + * - When a message is emitted via intercom, it's sent over the socket. + * + * @author Brian Reavis + */ + + var SocketBinding = function(socket, options, intercom) { + options = util.extend({ + id : null, + send : true, + receive : true + }, options); + + if (options.receive) { + var watchedEvents = []; + var onEventAdded = function(name, fn) { + if (watchedEvents.indexOf(name) === -1) { + watchedEvents.push(name); + socket.on(name, function(data) { + var id = (typeof options.id === 'function') ? options.id(name, data) : null; + var emit = (typeof options.receive === 'function') ? options.receive(name, data) : true; + if (emit || typeof emit !== 'boolean') { + intercom._emit(name, data, id); + } + }); + } + }; + + for (var name in intercom.handlers) { + for (var i = 0; i < intercom.handlers[name].length; i++) { + onEventAdded(name, intercom.handlers[name][i]); + } + } + + intercom._on('on', onEventAdded); + } + + if (options.send) { + intercom._on('emit', function(name, message) { + var emit = (typeof options.send === 'function') ? options.send(name, message) : true; + if (emit || typeof emit !== 'boolean') { + socket.emit(name, message); + } + }); + } + }; + + SocketBinding.factory = function(object, options, intercom) { + if (typeof object.socket === 'undefined') { return false }; + return new SocketBinding(object, options, intercom); + }; + + Intercom.bindings.push(SocketBinding); + return Intercom; +})(); diff --git a/examples/js/lib/intercom.min.js b/examples/js/lib/intercom.min.js new file mode 100644 index 0000000..eae56df --- /dev/null +++ b/examples/js/lib/intercom.min.js @@ -0,0 +1,12 @@ +/*! intercom.js | https://github.com/diy/intercom.js | Apache License (v2) */ +var Intercom=function(){var g=function(){};g.createInterface=function(b){return{on:function(a,c){"undefined"===typeof this[b]&&(this[b]={});this[b].hasOwnProperty(a)||(this[b][a]=[]);this[b][a].push(c)},off:function(a,c){"undefined"!==typeof this[b]&&this[b].hasOwnProperty(a)&&i.removeItem(c,this[b][a])},trigger:function(a){if("undefined"!==typeof this[b]&&this[b].hasOwnProperty(a))for(var c=Array.prototype.slice.call(arguments,1),e=0;eb&&(c=e,a.apply(this,arguments))}};i.extend=function(b,a){if("undefined"===typeof b||!b)b={};if("object"===typeof a)for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b};i.removeItem=function(b,a){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1);return a};var d=function(){var b=this,a=(new Date).getTime(); +this.origin=i.guid();this.lastMessage=a;this.bindings=[];this.receivedIDs={};this.previousValues={};a=function(){b._onStorageEvent.apply(b,arguments)};window.attachEvent?document.attachEvent("onstorage",a):window.addEventListener("storage",a,!1)};d.prototype._transaction=function(b){var a=this,c=!1,e=!1,p=null,d=function(){if(!c){var g=(new Date).getTime(),s=parseInt(f.getItem(l)||0);s&&1E3>g-s?(e||(a._on("storage",d),e=!0),p=window.setTimeout(d,20)):(c=!0,f.setItem(l,g),b(),e&&a._off("storage",d), +p&&window.clearTimeout(p),f.removeItem(l))}};d()};d.prototype._cleanup_emit=i.throttle(100,function(){this._transaction(function(){for(var b=(new Date).getTime()-t,a=0,c=JSON.parse(f.getItem(j)||"[]"),e=c.length-1;0<=e;e--)c[e].timestamp= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Simple selector that can be filtered directly, removing non-Elements + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + // Complex selector, compare the two sets, removing non-Elements + qualifier = jQuery.filter( qualifier, elements ); + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1; + } ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + return elem.contentDocument || jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + resolve.call( undefined, value ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.call( undefined, value ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( jQuery.isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ jQuery.camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ jQuery.camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( jQuery.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( jQuery.camelCase ); + } else { + key = jQuery.camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && jQuery.nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: jQuery.isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +function manipulationTarget( elem, content ) { + if ( jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return elem.getElementsByTagName( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rmargin = ( /^margin/ ); + +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + div.style.cssText = + "box-sizing:border-box;" + + "position:relative;display:block;" + + "margin:auto;border:1px;padding:1px;" + + "top:1%;width:50%"; + div.innerHTML = ""; + documentElement.appendChild( container ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = divStyle.marginLeft === "2px"; + boxSizingReliableVal = divStyle.width === "4px"; + + // Support: Android 4.0 - 4.3 only + // Some styles come back with percentage values, even though they shouldn't + div.style.marginRight = "50%"; + pixelMarginRightVal = divStyle.marginRight === "4px"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + + "padding:0;margin-top:1px;position:absolute"; + container.appendChild( div ); + + jQuery.extend( support, { + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelMarginRight: function() { + computeStyleTests(); + return pixelMarginRightVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + style = elem.style; + + computed = computed || getStyles( elem ); + + // Support: IE <=9 only + // getPropertyValue is only needed for .css('filter') (#12537) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i, + val = 0; + + // If we already have the right measurement, avoid augmentation + if ( extra === ( isBorderBox ? "border" : "content" ) ) { + i = 4; + + // Otherwise initialize for horizontal or vertical properties + } else { + i = name === "width" ? 1 : 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // At this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + + // At this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // At this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var val, + valueIsBorderBox = true, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + if ( elem.getClientRects().length ) { + val = elem.getBoundingClientRect()[ name ]; + } + + // Some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test( val ) ) { + return val; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && + ( support.boxSizingReliable() || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // Use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + "float": "cssFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || + ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + style[ name ] = value; + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || + ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + } ) : + getWidthOrHeight( elem, name, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = extra && getStyles( elem ), + subtract = extra && augmentWidthOrHeight( + elem, + name, + extra, + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles + ); + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ name ] = value; + value = jQuery.css( elem, name ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( !rmargin.test( prefix ) ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, timerId, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function raf() { + if ( timerId ) { + window.requestAnimationFrame( raf ); + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = jQuery.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 13 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = jQuery.camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( jQuery.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + if ( percent < 1 && length ) { + return remaining; + } else { + deferred.resolveWith( elem, [ animation ] ); + return false; + } + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( jQuery.isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + jQuery.proxy( result.stop, result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( jQuery.isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + // attach callbacks from options + return animation.progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( jQuery.isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + // Go to the end state if fx are off or if document is hidden + if ( jQuery.fx.off || document.hidden ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = jQuery.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Checks the timer has not already been removed + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + if ( timer() ) { + jQuery.fx.start(); + } else { + jQuery.timers.pop(); + } +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( !timerId ) { + timerId = window.requestAnimationFrame ? + window.requestAnimationFrame( raf ) : + window.setInterval( jQuery.fx.tick, jQuery.fx.interval ); + } +}; + +jQuery.fx.stop = function() { + if ( window.cancelAnimationFrame ) { + window.cancelAnimationFrame( timerId ); + } else { + window.clearInterval( timerId ); + } + + timerId = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + jQuery.nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( type === "string" ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = value.match( rnothtmlwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, isFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup contextmenu" ).split( " " ), + function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +} ); + +jQuery.fn.extend( { + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +} ); + + + + +support.focusin = "onfocusin" in window; + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = jQuery.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( jQuery.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = jQuery.isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( jQuery.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( jQuery.isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 13 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available, append data to url + if ( s.data ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( jQuery.isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/chalmers-fsmvis.PNG b/img/chalmers-fsmvis.PNG new file mode 100644 index 0000000000000000000000000000000000000000..18e4ed6484af97110d0f7972ad3fdee1bc44edd2 GIT binary patch literal 65759 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%0D%Gyl`m?96 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 |1$G{c4U~^4f!zQ^s`vB%iSUgCm z(mM69PccUp*2s0)zUW3^7fSg63b_m#x{n#m+APtKd6^fhWzgO50Ck>8_&1T53069On3IGFd3 zevnh-iH>h)CKVLN9a=d~@tE~*p_Fw&CYT`^1<{q`0Mi|_Idj5@XqlGo5>~!}X%`EOi z?VKD@xA^o%+J?GoIc)y}jce$WyNsMYadcMLIN$G{E;^L4T{^T70IiGZkTJgbqfjfm zuf=AR90LI9pIN0Pu;vo+x;Q@#oA-+x4QpbSq-^DC7;MM&QNy*^+U4uMNB0Cc6N>gy z{wnA@PMphux}>`y%@8qgXSrLo7Ul*3miqZq~;}$|VX0hM& zna}HC^OiiW%5#*U85)#Vk>}Ze;Sh~NbAI)=Iv$gWeHgG!dSpcpM&5~8T_5@87hJ@ZxFyyC!Wf1{0 z=3^w?T+MY=AaoTqN*&qizdq&F7gd*ekxE|*Fx@O;-ZG(t+cIjm8fm2a)Iv3b9A!(~ z9}@mZJ&hJx(p5#IIe)kv6MC&*CjVJ$F}CN4*mhzFJOF-69_x?S);=%7r%}$$#Ajpt zve%MV>MTCJPq?+`i1`?%!xTM}?;4!Ix#z@&+iTL-ZJKHOR%ktz)MC(>*JtRJ+}YOm zA>z=Avsv~U$-Ynn=jkLo`X+>TR8_PK*(3k^^eOmhuaL4;vwU3@f9{$UZm= z!U9-SK=zSF1Jogvm;uA)C{^PMu><+_ER)RjF~2scnOcvDPY`n)kiz3S`ygm8>ECfW z#O@mcDg+*(iaOC8MLwd9tn%ap8o$_)lIwX<#Gf{&KC@!k(DyrxanJreJb7NjoLSkq zK>K$wc;6)P#_kh>pM=HFEMTkl3ppJ%l)yzSeK5WEZ54C)HM`gNarr&D;BtA@KO}v$ zkjD|(Z!z1nI_}7wm`sWYIU(YCvF3tOtFM!E>>;8OrxFaBi*O7t)%CVH#G>!RyX|7t zaD7d#d-j{MwNq*>UitjJK|`Z)?($%hl*wu_z>^1D1DgMuOi?$sa!CC(>B$~~P^Qk= z(C;S5)A<7=Xb)e?HZPT@cuJA}rfx8Y(q{#M7)h&P!C8;Br5EUc+}|BlmT5~j%W#I| zlZGuy#t)+p+!*eJ81YA)pwCpzQr^KHw!$sg*Y}u$lZQm-&cWSRg_#+Aw27H#`8MIl z{&|6t4AsWSf$PHDn>V?y<4rAewGa;cXBYt~?(s}%LO@=raYLrv^xA69>iR`}J64kS zhqMx;RV^VWDLH-@JogQ>@%K75K`#iv0q{^a=c2c8xkXQg*oqiS@z*x$Le8(#h(Jev zvMvAkWdAM(qpr}RS;j$4R-qoxcZJqd5%zRj*R34Fig51h;0z(wy=I9x!&4=w z`;C|1(omQ&&+*)!gu2UEXY5ONW-`orP<4jyaNx*#QamuI&0JFYVn*8uLqHlnY#H(m zrK~yK>oVJ!uU;x@D;qIW__Yt0%1-HPtedJ=8Dlo#w5n{JsMsQ-$V~>SaB$9n8Oj~? zIcx}w74Bb?t=2&@C+iB*W8XJ^8zD=jvC>&X2_8JoJJd;BwL2Z`v%(CEHfL*k%-yq-i0_Zt)2r{9oc_=X%Ib9z zRF*kE399vl(sdc^7dz*;VSAl?jg#aYes14>!-pw*VtTKVN!S=4UaY7>fY*AxRb0T% zdp3JoRQqf;CMwi%vm}8KC>=TOefQskLdF6>)YTmogkgzYj>Rd`2)Id6U;J}B-ua^W zvLe3-IRI|iqdT@%j3$nOC$pK9a+svmm+VA>^SposZ{-;$9q>_54UoHcCAmjNV$)_R zDA-xoC#&*A`H`~2a%HU)T$mg3NvV~pod-Z>rBP;G!BmLE*sD0S0TVI_X7NC);%Qtp z$EIr~QS~|+Yj|O_Jg@_vVjamf*)+c($tUZ_!(Ysw@(z%3bFOk5t8ZF2b|M4t#EE|v z{AX$9DM@_N2z%h4pmx}G;KDWh46^?K$6$|2R0_ii*(*H}P*2T<6lbhD6x_{0hS*y% zLV{>V(_&=!U)Z~kb|2^LWjI7;``wE+j|!?*lFjA$rR&G>*S}U zin-@%iLhM>rMB4s(&5Y*^rE+}h}iGW`!a!F+qXPzT_;{;v4ggw|@9tGEY?32IG#1|2^Mjgn;mp%~f%#CsQH!6`#*2CDxtS z%IlJmV9A&Xfg!&;;=VH3O=M#-c|K;sh5aQGjzh``8G}8|Kv%B0zI*(iLa-57mfcm{SjKXL>9A_xF z%Q^4K((h~Q!@I#yh+756p92}`niD9=)#Z5>O(^7}VzC|vOt{(UuGd21DucpmF#~6^avH&xT@Q4`$O1`hI7|z zLt>!JQQof4iFYF6*rE;@*C+^0n0XbvE6sQAx<7wa?8R23#7{P4Hd7uIqfgWJldI!s z^aon#A1}xMM&5Zb>xC&9+{=#litm5G>njUVPYaw{pA9uwR8Ur0x(nTU?d$F`mq7%n z>L!OGg9`XD+9n&{qEV9#*~#(|HGfI^Ram)bxgOWeMbEoZxgF<D+Qori|FzrhG@b;uz;^l!};Qs z;a%P~PTr{z8Oimm_A{LueHr&TKF3atPNVP|%o4g|zAh`|6sOICg6$_{d;xqhd;} zW4}&r(Z4i$uoV~Q2FG-LxYvz?!x}K4+EVoiA%)KchA@g0_mtn^=YluCcBvXT^mpFh z%YasuQcbdD{fUV1(%}1a%wnN|P>Et8kMqdUntyVwQNN{7##0P|ZZV-njo+D8LUFgg z)SGOHaC{r6Kt z14KWobm0x7ev7`MYZz!Q{oDDDEv}|?;^$ZFHqUHQpEHd+v+oAWi$c0E)j9fkpBrN%Yl&j)i8>ra6}dvmq7*GqmWOgR@l|GQ6thPhMq7 z0SA893N37DPJ94`{8JiE9i*j3M56Aiy*OAmEa;{kDzO~-P^Z_mbvt%kxkO*-306(w zxc6IfI)|xUx$%KSv%6kqlnvx#S6fV;QP?9k%q(UHuxsS|zf)ej*pLy>(97l9kc8;b zfD!P{4ym!3ohbqpgL;}61nHuJ3Hw=-5pn+6`gr=L<%-_0u+&CaU=usAWe5rEILJhwr z8GGXSXqXtG-@coQU?Hj#|G=V@Lmia9`+VPExQfqN!R}&5iYQw~YbWJ41I>>I*GN1e zxD7BNz75kSZo>6~gRf7hFz*no2Z@EGD_N3Z@)l2oN*^PAHqA0z$hSu)9}Z8o8eJbH zHlL%fbNN2A)I*(_93OzuqyFhT92^zX;-gExeti|LmLd`CTx0L&+BZsu$Kax4F}+T5 zeC#Kj1DS(l$RT2xzQae3t_t`0r=xT@{9app*t{6*@bhw76!$Mh!G)dSJC80M*Ym|M zR8K$te|Kf{mo}@a<|*ZRq3;4;FX$k_^{$;Na(&;sCApPLQG_Hu+Q+sFAo-*OV&SDr zk_OSX1{JOKbQl1a=$BUlORz*8Dj~lpQI3qa&hzIIb+`&GfxZzG8wp;={(QzBBD^$Y zk$*3eO@*p@Im!h`FHCw-&ep%t)@r=Wru>`Y40U=Kn`xg|uG(YrvCK>wy20U5^cm`? z^U8?LiT=|2sO&^{ZgT5x?a7Ck!uY37G`?RX^zIjD92Ivk5KFK?dZm?yDZ&+#qRP;hSf`Ze~4Xn z0xy2oJetp)MIAix>@%Jy~*ux^AABTkvo>BJEqU2-Vkld(;@i8LR z3TgNllgwvc+xx^(G9xh3_B`*g^Nyg(M&AH zJ$c(RJzbK1kyrb@SuZPB10`gd>TybP))H9i+?g-79gNvfI5p15+m@TFSN{YXzcV~6 zp06S+FJ3} z_F`9;Q5rRqb~o{1jqJm<42a?t$IR>hR#W*xG2VKl+3S#2Md4aZ&P@g6%#HQv6NL>5 zL6bl&5?ONuDx{{Dd~>#!(7}6sUT5qhPG%j*Zr3$T4%tPBOU^h`X3jB>Zlz2;h`Us# z5d&OLZbr~V*do1>IY+mPw;*Kr>?o`>+7P9RZ@l+r(OdK1~!o+xk= zn%~iHp2Q@Oaw{1YMgtbJ;w8?ATp!0BJxle?&p#CH*<5lvAa353g5ErY?up4R<^I!UL(fAfVv7T!p}72hq0=)VG( zM8zM|cEKY~eRp5VaG0}vkjy9Zq;W?DqB#-S#hAlU1Qa#&U=BCQO{q4Rn0n=3SwvOuZg*tlENddy&K&=f z9{oEF@{lx(Rj)ycAe-zn-cJ*i!=FevdDa^-eu~Yir%yg43fnC?kctkc$$A*c>d+|V zQN31o-W`>wxO?s_V!L3sNFv{9jMCavcaA9Fdhr&5u4BOH#e(kA;}yd6s*fK;5473I zv3h0iZDgY)nK53>8Kh09;#Xh1ve(yW2%m3af7+hT-Vc2(nOzP3kfuX8%1-s#`t%2y zxLhP=sQ&at1DlTi@Fmt0*5R}F3pd?Y_cCRbmFDb3d=)?f$J)g@_h#51MyZ;>#mYof z8+X;Nci?E9!8_PF=Qo~E2ZJQ|i){#;S1!@xy`F}If=~z#RTxa`)-GLfN|{VfNB?>v zq_|v_q>VL9FZ;aQWxOGWcdIFQ*z8dnIOxF-pg$1@XzToWVyC7orfIJ3uXk@$$hzyLhE^ zZu)Xs@Fqk5UZKhDCtY2js<3xQ22IBH?ol0=dkv*Fyeky8)>E@num5!$$_i2S8t8+j zwG)-aiLB>jFGGF<2AmQn*0W`71!fNUYbNH42W)3y7uqbd78JQmOGB8U8gK)1PBg%- z>u&3&;rZ;L1v33d^^Y7^;@n3`G>k{rtf~hrU|+Uh&8l^BGK+sKFzBD-jjweqdyq?B z7SPGFZ=Mf_rSW(}A|%j3w{L*ciyN1K1`ozn@y&01ka`Jr^llveWE9B`3|42+2*en4 z2)cEd*?CKp^W3Bq@U-DX*lXHa{oF5AU0c(e9OHgl*w`KAp|?*IbAskXW`K}GYW2P+M~QlC`BOUWE;Z^F)xhiuo#a__ z?mUOG64;CEtNmP`(%$}qpDl$(x83NM%%Ab_ag1BAx5C*v$YkS}h`lwD~TP)Hx7 zVMl9D66a6l1w<5TwssZPdre1-z+e=FM1t;+aL)x$9EEKZripTX^+eN>R0%+L+9*KY z^Pg-jiEpSbdI1T|Lk8|!OG2$!5#LusKL~>c7it?DHyx^e%Puh!wTP9Nz&TA?B{ zNcX31ThuFCHAJX1^llWd`&VUmj@g^n1OWpY$Lq?O4EKr-SN46-MsoaVzERRC?0b8k zGq}$8PcG+tD?#!&YM!K~dLQ7q z50I54R+zp0WnmUXu6hxA{5`3?bxzYm1d1GSdj<@GX$Zn5@-V)Id-Q0xO?BwDXI(0` zd)ZrSJ=I$C!F4Il_)A^6>x>2d3`^U@#W6fS)sq$1A+3-KyS_XkeWBq>)m4;mo#xSi zdPAXPE>9So@GD#tJch0qDo;AOt|vOo7Oqg&o^RzRL{M?V!>dnoWJWS2qn z*@mbRJ-LazX*(CVP#Etl5)>7#&jxr$B1A(ZT&X7HmUWfxCYJ+$q@c|N%+<7h>78-K zmowisZ)~VP`wd(wJJh`8`^+@s1#%h*GC-yPvsM z{`;)wKd)}jKaRX9FO)46f4B%Fsc1$7vT2U?y)Tv_^@bf@Eh8lkB3A~#JG(mS zDM6=zN;@2Wq#i&lQ=D*d=MyyyE(dD7JRQyp`Rc|^v?tSSBSLq?cJFC!EF2XgX?7;^ z@Cv{uUJHlxUT41kY_G9}`l=rxs5dc-D}2%F|7e`u`~^_N>;s7|FQHw)oQasndaT`@ z-|QbY6CdI8XXlDijb4333)F*Vo^ypTX}veRBmfYy>pyp!Jj3k6JeY}R^(HWq#t=x$ zH~76Qt_($Hu@&D+lX-)m!U`siEPD^EF3lMBEu@wA%1xaf2-jmi91GcVp>Cd%jvH%{ z#j{O#XF5OWXn-~mJ76c|_1PjOSJLG$WN@ktYd8ZKJ{iNA$_}5M z90oV(webov_^Adax&PAd02urIxoXTLchO9L{;VLc7w}e`XU_9^7(y!#d|~`Jo*AvN*)2Qj69eHNxlZxoUWGZzb~&pDW5xL^+&Q44Ra zCk_JnFpGc&3C`9*3pp)6AOve<2F)%3`^<5@xt+fVV?e_>x{`+p=@wy@CaTgynG=V# z?dLVNhftiF5jVk*po*jH8>^2mPgW3@Ec1KwiLQ>H;$M>&alzd?H*J@i zv}%~c?UY@!$XH|T+Z!1>h$k0Jxci4 z?R#@*kYYjjlZmJf-jKBKU3p7c$mMf3#*NRcK3Q@@4~V$Tx#sWA*pSv+KTer4F-(z(U$tvNR?Dsi3k`d{T*LCL_%DHKe;~&=DRB zj<)TsVK=N?>LXZ-KQ^*vx`;zz&d-Db?sWA^C0GHdQtFHw=|C$xef=Eb9G5%zWpY`ZPNjPxD4bp90u4;Didf6!VhyTvXQs3K!45)vI@B zx@^AkTVdGJ;7()inM@B(i18FK{P?ar7;Pn3M}5*L3tIdTr=J8=1jYO~Occj_L)t|- zQ&z=h-JPO@388`{C05wy?K}IM_N$j3&>sR2-ghplty-I4Zh2;D6e38JefuNdoi|4O z6#7r7`!Ct9oZa^;K?~yzb~!UiM8;wZlQY6h zuN#s6oJ97F4MG17K}9uQ#0sDx&x_LGJnMU2?Y6_B4N2IjBakT>RhjR9Wf7Q$#fDQJ zW-6v$1gH=|e`@@Zx@zwFm|UtsCac@kIVw9bbGw=ubf!BXGI!5wRW5A*xMv>Ymqq^7 zD&I$ipdW|n$$2nvN*=+o_?eocV`*Td$XIv4C%vmz&oZqpZSKc{5$)WGJsWd`Q~Rg7yG1Gwj+57`|DrpO7l7F zTWTK8_=&lClAd+cGRJ;^qy~+)U9NoL15qe}sM)J0AiBQ_u^o|cK?Q!!aUZ{cJBS(a z_x@)|>ZuD4bM7nLThrD~2Iun3qx+>U&*r)WuNy?AXh2o~-nS_$rsd{b-)Ogu?F;n8 z@lXqSvlnKNms^S98=UAi#ZF$53G2IFx~Hn)q9xwV@^Xu(e~BH^q|YauS@W+!vyD*K z6URR9hHfB)f~~jS@!L~G;zg8JOf_8&!uzk--_tCh`K$#3ajGY@+k=j2H*@ml4?r{T z)!}SyRmr^s|C+qbm^$`NxJ8UqQ$w9qn#R-1H~%K7s2JbV6J7juGraI-*nkreU~g{@ zrrpXhkp#wi18#*=Ga{mU$%}2~*4;J0IX;`8D3Afut$d&aSMpMJK#|vB`eE;)s`yEE zOZjN$!~#$z$X1ON90O!uJw{!Q9=NR$2G!#NMkelNONc2fx8jODOi;ano1~zrdf<7j zE8Rt4U>fl*YQY@#t-lBz`q$~>s|f`Smc_Fr@UG~RQ6cyAtPI%|mQ~pW7E3e+$|9JRQMp+QycC{4Q|Nb@sVOt7GcM#!&~uf4$q} zj@*u@AT`lsye86iUent?wFj0#a6*DSuQEw12U0kHQ|mxjEn;?kRM+zjq3W38wXjn@ zB5tC)^WW)uGR)JNH_Z?c+bdxN@mGdV)N2@+36w%kY&SdzYxyAG7rywMnn|^yH_aYp z<4$_-G=uieU(01L>m*93B_d!a2SJT`mDr}}bYvOFta=Kw11}R0)Q0nB7O7{T_ktQ6 z17=5fwW(wyg>wG(i4@Jrj z5Uf={L9u)VIGA~5S=We#x4X3O#e5c@UK{dU=|F>!JNPfRb#x9cJ{g53`{7<+3{cWF8fm zVqvFqw(MJ93P<9I#Fn$GrC_R|9@@A0xkY1QKO3(*{DWMhnLa}?cK~$}3vG`ysXZ9~ zqh`4L)lp@K@U=CZ@&7}w{hwE0D^9ZcNWS}7tf;92`tI3svD3CQC~g@Y@Rke!RwPRI9OIx(| zC`xPZy(%_E6+x+1t=dY>lA`u%?7fM-N4U<-m(@b>cqE zJVp{?Z%x*@hE)5mHedKy5PL*wo10$VT2&VF#Ub@@F=eHcCHXT|Ue}CONFS4N66cw#ED)>I7<@EoX6S(*OE9?c!E-CfvH&<=z@zDCuN^XAksoR9P z5fNlP`!mb&zMfD&SS&}DUc(%n*__=;~UOptwo!(R_gd`4{+Jq4Ov_X!8D zy1M1rXya(w2{wz?Jz=-|D1?~43bSfT5uAc_J5rX9F%lTo2m1a~2{_lk!+atZ>d&54 zV0)r>V*1lb=HBZ;>dp`#64bUTt#d6kq&xDH+Ag&o5$AwQj)2+a06WMcNbv$_bx%KF zAfP=W+3!)cU9Axz&6RJ4ltR7+CZA{m;h$zNdD*|>+Y@=Yo8?qw1e*f^zSyJRV|mI8 z;}$dhMXUbIu-p|DXCu(TT_O=bP7WKtw>*Z~SG3KMr=uHwM|G8be{^pTbXfJKvh=YZ zbD2;CaIO4Ux!~%zdRv^2uAt30U6Kbo{N^NXmE|4_#Q10^0EJ5zUeT=cwXc)Bz3&om ze0@x4FueF+yNv7w{v&heZ2x(Lt6656%4@mu?2}|VhCGX*WA58KosIvSFHZo$B@*`# zH63ut{)KO6WNhw2%@N!O&;=tNz>W@W#l6Y}=*!Qs0p9fYvL* zR=3mQyATt|YB$JQgKel6Ro3T-*ppFqHC`pQBv{e!2!8xqf_Fpb!q$I(D_R?XkzHP) zl@ktSBAPc8s^tyoK)x<}|9AY;yrxuQ;r&y-b5WyO5D4?HY;K^7>1|jKy|_u>zLr{X z*O#>LyL(UJTplI;+^2zaV2=S+C&*{L$$N8S>7M#n3iwn8p-AGV?!Yh)rJbgNm_j`G zR+DBQ#9t`;seasH%HWR$=Whcm6yEaypg;GWt<^OxsC(=`z{0E4A4mpgVIrW!GW&%c z|J&kze^=O>c3wCe#5By6m16-s&(ueamA&=FkPhRelzCrU`J8}QFM1r94*~C_ke51S z{r$FsgOxs6{&El=>1Ubu{kCMs?uD><8 z@`arQ<{p{F|8`bk`E#UW$iQhbBS&@k`%7mGufGV{3YGA&PMve#eKdpO@uYOteua}j z?El`BG%4PB^+UT#`Ubm1PR8YB9(ahAi&HbjYK#ju)v;jB@N;cL4*7#Ns^!y3<(B1h zo^=D%oZ1|KOQz0?@jK0FBQ$SfB124jfV(Lck5~!Om~Wz_o1M%sMGC23BI8@x{-^OX zIYFm!Z0S@S*OkzcQr6=wJr8&%*PN>hfqJOXMz`xWw1qR+a^Y|D^!Tk1o94AGzKNoQ zPknqJ5>#8tfBULL-NBNY1W23yxRfJ$5om2S&Am+TTcNHIxor)CQ*vG2Snzp1q!dwa$y^{J2XlFfQ}N(Q@CA4RF)&OMBBm^9 zotG~?Bfk-FeduL#Y`9uW_XUEL_HMak55#Z81wKI^HK6BTr;H5s z?i_IMv$H_DA#K;o(-M*rany#;^BgJ<&JC`yq+_zg2kbgro7ybx`3mO{8>%JgW0Zyt z+wOmI2^Y*+#Yy5YoAtW4foIDlVt3VL3s}a;u#`o6zl$Ra&{JU5T5SA(wABBb0pLf8 z1=)IQR#ukPL~99Cz$}mcKlgRU;&l84IZ&xo{?DKMHjB1Jdbd%hd6kufY^y2EKi;50 zAQ$n0>(0*d@22H^p)=O$@A^z6LCz%8gz#E{ng=9=4w z5uf7BVs~kPd)!QogPA=N-u6n;ym{$q@of-*Y=9WY6U6HUb$_Va43a<;(3uN8IgsK^ zm(C%qgQd~SyWY=j3nI0y~DxZvJd*_Fu{(|S8VYzN^DJ8D4>E^cm zNh(e0NcIlz{|HUMo0V97N8xc$KuZis_l~-w?Yr^h*0E+<-a{9>e05_(%m{CI!t<|? zo>;FA)bsC&VBeJ@z)&Hr`I`M~X;vJmW#&0JQ~rEv^Ha(f#-?btowM>|0`NrdS5kPF zoZq{k8yl#0<;S-lcF;eO;F01QTLcYsSy+e>$)5;30DK`@rl0=~qdsa^DcJMX>_#R9 z1)$8-=kn22(o)1u%yUm+qHOz_=Ta0v&1P0ajiKi7(bEYnj6W;kv*So{j685T&_njx znlnu-R}Q91*Ow6dhs1M21EOLD`$P|bBbo)dw9O{yVI7A zOS+tiAs+}!GttUhvaUnvBNv$qXmmZotsHRa9DK8t2}9re1oyzJ`cWI93 z@6zxOvjbW);J@joK$%a_9es05DNMfA^}mIc-|W&?a3&l{;IMkrqD1I~lr{%BZX?+~ zl3hN2K(wP370)^zE;mX)hy_>2MVHoehm~VX###l-op@<3Q*#JoR<+TEm1!?fO zoun`MV)ZI_{jM3_D&SCiBEN0*JX7yo-C~Tnf3^6XbYY2kOx?eaX#gbgA+_?Tyxakx z=J&t78qc;Vxt>>$+0V2|e$rv)MH}1_(^49_#|-)ENmtNUKwM%PD@DA0^e5d7vfa-fV*`Ahb2j`CtCOIlvOybgFfv>n1+o~L^PmEQXEnG#tUBGw2nXFHO|mR$^L!(rKcj*GJH3G&Eg|Xz9ypl(2rClL~PK?{`q(x zJxMour)Hc%F*aSqT1UX&1%xG0>U>dmBpha@%?KrWnY?>DfA8Ni) z%Nu+(&UM~i*Wx%smQ_yLAcne{;`qfbLY)m`&t4TqZ#U*63I3Usb8bsK*RTAO8jw+a zy_fAELtvq+mg(@ukqZY9ND0EuD%LI&My9p%0>*zgh&by`mDqX-vJK!B|H_$dv42b= zM5Uy+81l5r=Sfj}Q2bd&f+VR4F)l8%_Lgw$`##cnnOimD@QwD?N>}a&JK=LO2MiS+ z&(O39SE{TllE)}Z_;-GKb>iIniI>)J-_AJChDzRm@0nmTDra^xOEKV#Uf{b{zgF=I ztHlb78GXr>Nt?&E+50CdS1zBO*Ti7wuDzP+*cZIuZp?jUDbU1$IMt51S(X&9+KYqo z{lNHwAI_e`iLjLpBHO5r3AL#&l_E~mMr`OmUvKH#M~TkzTG)J)h{?tb+ekRUe#X`4RlnAZBI{P8U~HidzA*M6b7y>7AN z;QH5_K7zJTVuX{RP9Rex(($(L^~9-obu-+>rp1J)UbEWOWi2m*jL(a@n%yOpVYYOb z%pJ`&#-A#{;RU3b<}0f^Q$TJU8*oEzz7Ex=6c@y%$}QE-0cJ zgpBOSz8c7W{f(7}-O>9XLjG;v~d7>bPu)nnw<%_r4EAsHskKl6f8a|0)JZ*d7z9`>AP~fS9BvB0_k?RImUbpKx zYnEYGoKa(n+}vSyQyg8 zH`LZtbjR+~X_|V_C`I|Y>$h}eGI+Ma82oka<~BCa*HLQOYiXDK0W>4A?Cb<#NGeeO ztK3D1^2vm>vYR+u>LYINgp2@ln3nSzUJ-qqwGS_OF2t=$>pcx*VNlKBap3?}VQ7WW zly}e=(tic9!N}J^*s@Ll$S8yE^tw6_nP)#6_wI?0xEI&9P~F^JA*OIZ9aF}BqFA!nKU=cu8!(drI}37?d#_|nv0 zSv?Lpk@Y|%99#jHN_0!AVJT~N@_#CUwj_N4BwzDos3H;}5h4iwJzm%VxPB0;yG$1H z{(!zsGzJs@Mj3PUMyq)OUyD&b-5gM02 z#U=PxopHmE;iGdj8P&t!Es zWSF4s`mn!n&JQNZwG}v&5NO*9S&BV5ujH=`m)?!;)C_4PP;SNsYM?=u-=!@Vd$ zq_w=90cKk%VJ?U9mad~cev+by6gQLQ6+pziGKTVAPPO85*(Fk>?ZOa~T-b>IGJMy3 z$qA9DWZlag>h+>E1jZ{rJGI7>Ic;jq9la|X1l zM2s1e6->d>^e&Lf%{;mgRKpyLu*ujH(v7H|$GXIOY#GX&X}*+-3{N;jn8^qRS3WVl zG%yWP2_9yUdb*~ri=_leQ7?;*W96iX3%`mq4l$Mm>cyBq#1A}w2E&M<7$ zFAOzU8FA(elgq{vI{zFCA2Zn78}681$KE}LCQ5iXm(43FXI>D7q2b@6Uwxi6zjg@x zoVubI7MNM?>^4=TM>uh6jq!F8W@R`5E_2Fj4Z>YxZLO$Kt$B}_q*lY9O1b@tPJ42= zfBVj8J48k)U?RHd<{t7jV^h4*iM9L6euSgf%Xg*gTeKOPqbkjC+XG67F~Wn;&QiDF zy_chuxytDSP!D(qw|<6Jj&wG--eo#c0^+uY zrMYyFHvI!{k2PyP7tv390bIK`Q-Ctqr{$ee5UaE*@6E8Y7XZVipV}Xr69u5lYwaCo z$XikKvp(y}SZUEz{GnIs3l7d(gEfWUVr#XS*@bSuiW%b@bfA}q*X4bWRNaj{OX;n+ zOaF_-cKI3jr`qbY9Ep@E!QgIQ@!2o3^`p@{$7K=#+*XPu>!Mg)a2VC1^OL2Uig9SZFOG?F{D?>#Cjo_uxT#AJEa~k%=<0(+iXci!&tlH4-6CM}K9; z%8tJ@b}YcBIR9WYW!1kBgx8&(OfbRh-=SzUz4Ky?)toU2S?dAQ_D=diPDbL&vacYz z3!-_Hu!Qax`7gj?=rcbIPMTo?Zp9ZXS$kQbth-$!dWIOq^| zkcG&&YpNqQxK>VwOwU$PYnQkEX?T(6{ipXeCcLbZ-L*L{CtHh?3H-$d!O@O zO()z}9y>pt_01Ku1n0%rU+}J10O~l1o=F;-sQkY5^l`f0tC)sX%psr z8BA7!h0Z0q>G$B1ls-V|D+MOEuu)@j%@|Ex^+XtRAP@sZk8N~b@_S24K(bqqc}WT@f)3|`LB3l^acl%H#d zt@;}@-zc}VE16OKr99CiTq+wuig!{c9NaZ}8e^$wuh(8PDYiYdD1*Ft9ID6GpS>|{ zWEz|7@8m!B_cxQOPgbqGZ%?|*FITqwhZ?%nfB5K*Yi)&MOpj;CofB}p|8pRbIUxo+ z0!MpEKZtaGf(46WrbYgis+U}vpDT|=vNUlMlt`#xL=UvT^V3x(1Cjx<4_cXnCN_d3kwY=yA{{NY;)kQOmlpc8o@y zJqw>rK!2l^z5Ubg2HQDH*A`bHI*D{bW-q3qZqo1=$Qztnni`~f+xCZlk9WPI@9b&8 zx~_1ZfI88qpu zE!T|JBYwC?*@sZQ=(lg`W;xwH4A5Mt8eU_R|10&6|3`Ua$$se^MP@GTO8~!AwbW1LdQB zhy~fiqQ>0Ayg?gu#Jon6$A6A-;aI50VHzBMHnw2!Ie$fwUY?h+>Z-dlGICmRCF|xz z#7acEOk(iqH868eX3f*L%mZX)uoIu7@qC)ro5iP6#i4lv1Nnd#l|dOBcDBBYVrLN`=p&!6>^EHRFv<|#dEqcemo33K=^Sj?UU2`>-Eue zO2O|ZN!VKBk;j{Qa+-;Z7Idl1TrZkE%paEwOUq=_A9(kri?MsaA0E8KxD31yW23W}u0a)q~Fj7AtsOGH4PO^xv;vRCTq(!rAJx@@7=kxPjc9 za>g&(AU#4LdH9AdMbF{+M<^$2L>q3y!Fn$viLAaiyt%1-CV7n7(^Zm?`a|lZ>GKN) z_zK6CY~hD5oiAJ}lwIGJHAxXu-$&h29~%X!#v&E6O%qN|UY4ci8(XPX?hIXfJ!#{cSj%G(6E zqi>AxNCuo1r^!17%ynv#pY+656b^15CjJyirz21d7?zZ$3d8)okEHlVU@k z^^(6CWeMfWYVr2=U8``la-0A80&2VAf14JDG^=d@-#$2PNqv63@%EX4(JlDbMbNj5 zkgxu^{x224V{?&}Iu5??Ga|17a19wb z(@ptDJ0qh$%-^b}92%Wymq*eey3%M7`yHF=AX(_n-P{EUc!f&{j5PPP7~}}`n=i)* zWDVQ^%|(BE!M$-q#oRc|x?R0^)r0^y=R5Wlm800ln=9lo_YtOwOdBhP)Q<@ZMObfJ z_YrJx8HgbT3Zp-B`8^MxZ%E$?)uWnXa#~?(WF7K+I7PD_hW8V!N+O|sSuHwr<@C$> z5-r}g-gfGowwuIZHIB$PdEWXrx>RbOZt$-XR+r0_H}k^^ZHtorNDb<27LnE>cs2*= z$j~Hnt?`9#vY9^a?$V$?AKLh-rBA0`!8LavaO<=VcME0#7+?fGz4d|z?R>J`Ms*+R zM18&XIL$4}e&|iFdt9l(t?oePu0!JVqXnqPj$g*c;>h7YgJeM(;bCke^FubU&0xm( zH@vbxh{#9}jvxac?kg8lxf_~dqi2EL>UhDWznM|MaQ>LC+RDQh-;%}1GYEjGgDHZJ zc)l`WL?Nl!QhU0{8TwB|GUxX5pFjDh85G(6d$ck@5@9m(Fuv*H+oB#cyDN@{)lp`- zCkLw{i+K$Q@_utxWL{Z6Xrkj(s1!{)>OB_s83SOCGSBWn_us*IbZ`RmlKm<$j6TCj zf&Ni4Xz}q6ft2C!L<%acV+id3TkFSkwc%0(h&;8H)z;}Uv^R>8mFS7L=(VHPYI%u|-dX+Z(UT8?{Z``z z*?FS`qB>|&;OR#axhz#;OB~O&0-0XQ7PO#EFJuFslu1w%iLb|XPSWVwy)}U1n%w!i zg;@9PfAcgC*#IG1_`ANe=|d6h_5sdSLHV_up)jsJ0Lvv{nfXyxgM4BC3c$twX?k~D z>4|IZ(c#*nT@8M2qMW;TebngTX;=DM|55wm&QldJUSpSA(|Rz36|nVj`U~HT)|fs5 z9$;*=d{mn)_j=dnJt6vOU_x}@=vycL^?oWdNSsYJ41gGQ8Hu0e6PvN)?O zX{1KQ5{*o=6jDc1Pl7y&SCt0?6uX>Z^yKFW^olscaj{O{Zh0bB?I}nQ9kCNl8~&dT z#=G<}0}~ITz`;KR+cynZ*m@t6UaJBjIyp?49b-Ngxa%%qh={JEON0wO;FsBr{x$oV zM8)$>^$%(V(iszP62AZD5WuBz(~!ytbo|o9Y!&|e1lQ$ZPWL3G)7{zN&%sZD*U@It z-vG)uDUQy!>;l&>=2`xF5^_BmxfI*|MnxT*ot)@GGH8ladT{YYjs8OU%A2eE>%|X@ zPuF_V4tN;p)IS<-W1(luyST@4aoQ)=ZY@WW%%w|=qtvl9h)>IrE}gC_2w7J{_m>R1$y zsk`hVlMf<(9<~{%@-o}%q<^|TSnrqE%s(b014%4^?!08dNtQcUuOA1#a&6*U>eGc6#3%UtHCRN-t_YS=`S!KV+EzjM5+r$$_pS+OjM~ zen2^SU~XDb#hD6Bx_BY_1r*F!}Q~HqKg$zi6Bd&2Q9m zIdf8jwBF^jCp~@Hv=@ABa=0DQb7A;0-4(LgEoXBmqw01Lr(3z_$zyMj5_=+iOIIao zja6Rdn_%>}dTtLkd%(~a+~M%GWV1Gr$jbDOQOKb1W$OToqS%ZFIeXFZZ zhv1iSmjAjs@6>spU@6ZDVR=@ynf6-fUhV0RsFIP0<{T@!TgXqX6O z^GsVob?2c5R{D`-*kVX@x=My~m(x&=!?bN1$_G)Xh6n;OS)fiP|t z_RZcu`#$qC%iqm^V6b|4gCSAG!Ulf*bq+VQ!CUKAZ>(JhN7!nUUp-KnQ?23w`n|x8 z(guDN6-3P*xD`c*`qFe;WB8p2#8=ZWlqstwYGt?mwp(j?O(NUkYmEH4Y8dY_O+F=%$@+*tc9{LDft-~hsyeoA7*R+mDVgP? zKd_ctu=QCv_;oa|D}t^zV>9XAB7Fuh+}aU6!2j8w7^{qAESm)^Q;RE@nLXLJ`iKcs zTPVH*f;fl&I&3YhKY+bWwK%<+w*O}YkO~?zFz&^6v{wKdflA=|QBwjxu{rMYGDBF* zCTu?FGqTB#)8c#@Wh?xXKF#)GwNzn8_wb&)g-n4Lkfi{3>5|*U>@X9!>oF@iTL7Pn zUo$aI(JfJTq70&UQ3;Xv1lR3RKh?frG=pG8s^(l+c-K4p2MDiXqLhGLqy=o`_0}5A z#los;9tQ@PEc#x+itU%H7JityJG%)NiTJUi@iPxU43kt#6J3{ z;e6xxXKO=m*Lt>%mX;Q>I9bD+%=?FRe4Q-(YBCpjC0Sl^Kb!5mxQ)EF@rPPXylDip zhV*lHj)OXnX=c6OdMJPJoT~J6L7NQg8@4{+{<5AUDB@tUJf>)rbTc#r!K&_rf$^jl}C1lMexPbFlzzL|Pd06YHH*Qo;Ka~pIn z{?nywsfkBTR8p|Vr$T>D!`V?`>Q|ELE9gq?^Cdc`AHffb9vzW>oew7vhm(EUhD6RZ0@mI349lPeyd6|Q3ZMJOSr$SA|yz1&K0N1sY7x5AAtGzFo%HC?i-J#S84D!}xxQN3tZu0K=nnu10{mz{3`2K zdY{~Eu@Kma5~hVIC{*Yuz})oO&{JtIHCwt)`yK=QEmt8IHZ`&?IUh-d`j~Zd#*TmC zx>Wuk8@^<3MG4y1CVNEuVDbGFkdizIOx=-6%%TVppU;qHAfFt=M3UyNMT2b8Ca=Bl zg_Y{?g`)Szz}esMV$0A|nQ;DsjKfW8^3I|jOZJg@R~dI>V&B)ob7bGY;m>Hl?Mv%PhS66ycS%nu*ltoOj@dk8yT_67d;F+ok=sP z7El$;q}gmSCVYXX-}%Dzg`Up%=VJpkD9Mb578k;;!K*X6kdKpr@Mhu%l+Vy=5VX0X zlATC6pPUvIiFOR^7{#|qdSJt21ntbYAF`8yQt8ChXGV8Jj8UgipE!U&gD^P@Y$rd~lz{Mm}9h`URDcQ|Tif5(eMcgW%Z&m$c}fq;ozcqdWGPld?CE183O?<`dPR zrz}~Pp~ae4O{FE@U)jh;RA%KsW<5?fuveHZJu9T@-0WRek_Jx~c!ZAgLqOs5a`SZH zS>u#=ZQA$MqkdnsanUA=kTO27$y=M@c{unlYGtB;5Mc(|zdJaInwYzY+@oEU&QuHp zDkoq7dmZi+FF5P97os&Ex>gc--~#6i5V8_d&4($AO2FVvJ&_RIi9~rabucx>V{0IN z1MG~8;vnzElb^~lmm9N^EV}adLE6?sV`F>19Pznwhg%7tS&J!r|A-xD40Go_e$i{V zlze9aU(5eb&8LmC%UzgQ_k z+QaG!(JV%(#OXiRH0q(x+39#OV-~P;60>Qk%um(BodqGj^BM)9paUT)c{TBF(cK83J@GJKuyb0EldV;=y^DWuYo3_+Fo2XRyG3Ct`IkK>wVf#(xL zyl^|CA2*7sc#a^6<3`K^@bcm(Mn6#7++pvdP_xBkNE#%_Nr7-q+MfP9C*t0!=WD89 z0DWB%QMD=$8rng1QccewpKXT9^u$WMkp2``OxPm7txV7$i#SWOn@I5^rE{pLf=pMXHhS(&RX_JV&GYHq48aOp)#t&+A4cLJFT?!Fwx? zN4Xj2Mr7^sbFRbNbn$@y^~i%(mxp6tV~zn$3$DFMCEsV-CT$>2J8#&WHOvt{HTm{J zYqcn*+sj?=5}f8aeaF9CpFdQJC$FCZADbjhB~UWsY!|Q~!3-3gAq2?6sVqYmsNC%M zm{VK<5K}t|7^yZzWu7qqb6^8>SJ;Z+Qh#HHOFeGwgv=ZF9)Mez2sEH05`!NE#fM6! zwDx{RwZx+Wfu8D%=j~17@{(~<@>Md*Xcz(y?ai*J2ynU$R4bYkgvhBOQPI!%S}QKq zl8f&GS{7bw!CF>mLN`a^eV(u(g^=48cZqHvt-SU1tvcr{=q3+Ne14rFQSS`0<#Q_2 zgbx>lmQm!fhQS@4Ej$iS8hf;u>hxB@0OF*yY;}0|ns&*Y-1ia*Y zF0C>#9e*gW@4=op#A(L|02>S~|2|Hil&n6{P*^6=8{ZD^AO|gQzdws;Ny9W!s^;^I zxuOa39^Sn0`q6@z8<@|Go{cZWBs!J;GnCB-DbihZ*Sb|hzS!PlOealUd#-t=k`8}- zQemmm3p|`w|8b;x7l!d4I(_OK5{3_3oYy!78VWzXOB|;zMnK_;xFRmU8<4Lm z!2ml&V{QaB$EbFHky6n>`>*N%Pc`|vo(2QPj#QfbQ}y6lJG#Fjanl5cpak%akUhhd zZW~7bxYHZ$Z@mavU>nM`C(pv)Z`=v!tL(Eh0o%Ogcb#OrubRj1(S0&jUU~0>_2L;b zR~8pq#WR=Fv5mFugmj*T@a3FPl1bNW>7{@C#aumBz30cZ{Ej7O_jlG~*WnGR{C3`e znXzu0Yr|%t3JLTJMT6AxsixH(dt8tiNB+SopbOlWyf@}`T_)lo@i@*hNDHl$Rx6D0 zz}^veT)7E83cusavETHeUdJXnDR!7j`qrvV<#LK(1dsA}BP*?Bg>};={KIksO#bF2jwsor zu$T*aH>pAcyK<)2*e9|(J!|R_7kwA*Y54jxJZo!a-ImXC&ec^FU3Z+vTdQBh6#`4uU-vxWVZh`5Mx(S8a9K=wSXncFu`)uKe^+rjV4IJ&SUmWi zDncWy?{OZ8Z?FQj^rJ(%m5*L~KwXLcCyVZEOipkh*RisfqO3F=xjaaC8 zflUxR-d*_;Nf~Bk=-F<`ULd~ceL_APx8`%4EX#cAyI9p><@v$?T%}n;brZ=XahN&M z&FKN#0=Pllm)0adGcxi8R%_7VZZf$c|8 zoin!iJZrMgSlO2PoVxQZM(!xCB`_J2=EMzJfIH#K3M1A z62Mb0FO_M`k?!0o(URlB6Zp<`&UD7k-9mDY5Y&7<_thv?=Ez3hXi`KOBAJVW*c3p9H@*h4Ov-ohtfF| zMI|E@sd9@rTe&T~3`*}Z>4R1uYeb-C-^-}cc|jy0zntlx##Y@T3R~&>Y=}MoV8W~F zu)?jB_(r*_@4*%u4HySxpmdR-bM6~g_zpaJL0o`q^R{9Y$D0FRzD@F|73h#OYF~Wb zD(Dqi|3_l`4q3X?2+S?a_J|+mtx!CvHD2jl*(lXB^MvB1RY0%Q>sE=wj*B2ylsi!V z)2W*?vs>9A_6@#l?;Gx4y2xz)QR28VdvFp(C;m(~_IF=XL#eEm*tq&A*)t`EJ%*fy zJ5bpzZjL|!fddwx(0p@H-XXg7d*pz1a)5?ChK+2Wk}xY-b&Te$PYfyb;JD~RE4`Ge zRo_jfe$P6Ec|d$E36S6(8|dLaQMaA~Ot9Jt4vxloc}U&jx6_aCmQjW_@%g5h28xMv zv*uU)C!)5BYc!jK>>tKknMLFmJC}c5eqUs@$XpnC{y#|?YJ%rJzR!R_0A0Vr>>6M} z0p0+Mk-`GVy_X#R-O|KBjP2o9@`ba5(QMD7CXYk=*e8@3FpK)dX^TPqFcZw`uD2Lb zAuS=4GjMI;c(sq5R@EUNRi-sv7$T0KRdcv4lUb8v`56UQtTe$3`mn_cDx6S5(KIi- znHERnS_eILtjroe>KU1Y=P@WhhR#dV&#qT?u|Lk=km;Iv4Oj5hnBZM`nmnWi!ap7> zRUTJxc7qLcUow^=O%o)*_=dJaRo^T2wP9(}eHV<+5ZzyIh448nPaqBH+>U^e03Q>>3$N z4vDR!q0Vxcvx4vv@tE!++8m!Z{%xxDbkj7i4&0Y6{{C859yD3;Yw{fW!cUafKe%zj z*~}?j2>`&K;^^QqygY?CD(a7Q%UgD7WhuVYUg~2PW%A8D6AEe{<-sqx#UH1!6&K|Z z<9Ce zj7GNT$!66yzJQ)X|iSr3NrB`o0^sZPEY7+=^g-8;)p2jqq>D0miQ1lcR?FW6H)V>OuVo%&7 zGvjWI^U5PDxy{@Z`=t=eb_+pU;S+@fd9ZJ-B`m8n!I^e?S+7VBvC`IX+9#{1Fs8_U zJ@S#+uJYdYNtJEvw~mX}dM;{IAx7=EjR$dSo7 z%!9j(YXZ&;B+zK*B^$U1e*H)bfUVWaWn``~x`sTcJJ$<&;Hr2^+AGCQn^E7fG7VH@ z{b5hVI1m9tcmBICL=*Jc5u#{?EX|>=zacGrL=MZ`p|_I{aEr$f-k;n#3h86n3%v>#2M(463)i%OX!46`V{L_#NyMWDz%2({GskVFNBt;V`(E%p?d%2c`W5CxxR1Q+gU#hc zr&zlh?h6Mi%OMS9&0Ed53lgsKvTN#kR$2+(SPf%&k z#Qo_o9FzBWG=Y_aC|i55N(~XW1C?u`ug63-k4azy@Xpt*e63E5b;c>E)}TWf@U&me zbh^7m#q(yA8 zS6wIp_YkMC?lu9!1LV_r^&i+Wax#yK2z5Lq2!pPMTt$ZCt^t(x_~pLOvH6VYGZFMt zO`J&TF+9)JSp-SRN{8CWngJl6U@uuUxM@%C_&W^um{CB!MT` z2PEw|H(~v0boj2Hx@v5E9qe`;St4XJa`MYU?=GnR>AjPISh~BBQ=^E$*yvOtYZm_7 zLd=vRwRcj%*R+-3K!zZ*{y#xa(_y(6>bKO;bJ-6m=-siDm}M1H8uf(E4bQ2hO_TRYy31dR&kkP*Tdi@$F`{uN2cz^s2q*b)uZP9jLz@41d6cVR8Cln&8Lki0lTu@}vU5#^ocpM|la_-(Q5jrg4ydx_1PzT>Pc!uk1 z$7>Sj{gc^gBP7hd+V9OUyx_Qwyn7je4%j+!uyn5In~VFP&xIIBmJ z{I-`&ONZ3Bwjv*Pq}>yH`eu8?JPy&!V}il#YQ^GLkH#(KrJY-h7X2eW^)*pU%Ze?JLU^ft2|pa1d^@SE zGNZQT&wi09>H_>S1nrFV)kjc;JWao|;UWWC?LG`@VppXvH{p-goPA-8TXEFJ(fsj! zMp&@sjF@_ryTkbg60$6*i22O~YkdoWy#K|^_F2dWjdJ_L89#t_F|ke7*pJ5R3F#=f z=F*gWPuN=)eF5mZNbgZEi1kH3mG*dQsD}mr!h6XFhWStIX2^faqnB~}DanF<(c{y; z`lEz@)-H4yB*I$!eb%|)oq*1@YR>&r?ML9`ed z8am8cKG%<@w5jJsZ{?}C=Cs&>&0_)MGg(4=s(+ z4O@iU?N!;q8B~`G2eEZ=#8Nl3whB?#8&pl+VbKd*HG34>bWtPTc0ta|Sy)aR4s}2D z#`|;-@N%PE;zv0qgAkuBOA)=JkQ&R^%98ll<-nH>rV9j-k!%Z9W4)0QKjHk==riPK|GRcA{sS7#i-B94_+k5Z}~3;>vmH6 zl4HZ^=OQo1^ivXdhuc&TzDU}+>NTJCq-cM`K$vw*ycq`;+P+CxoSJe-3hGWe%F!c!3vvxE+XbD``MgNuOv54-Bh=v80J<)j>V{Ji8GK&92`c zoq0c$-t0v)sbDj7JVoacW+{Y1*love#(&95xYA5(^K3VZwG0D_$ast9=W2yKS6{16 zP~vo7kyP}F&eQ%>XJhHp4=ico6xKUzD8X4*A*G?NpVG>6q(rMkbBbf7Q1=&N<|-^U z%qiZKWlD_op5GY&J?A8PBWC9XYpptr9`m)tWN**QS~vlUoC|G)l$||o+8H&iCx`b+ z-UXuSiaTn<o$$B>e*CK|~+rZTLo&3FQHU@YA2k&qcNb2LzJzZ*a0{C!F);qAu91raMkR?=@oR-Uv zfwnAfUix_4xayH}yN_uYkgS%@ZY0QO!Z49IrSBF~|8ufqq$HzF2cs8EZcLIvPCUU;Cwj ztDz~vMtZNMa#&%nRpiJ(81nP1mz?ByYh3v4jvfn{g)HK}dRSbyitg3K>{(-KGQuWc zWB8HX5hvco1%9i|Q1*Cd%kiTB)cEe_O3rM@#OZR{9juUJ$Haby`x`9eaq=;^tG@8d z72pJRuWin;y~5GN2_b#%D;Bc5%-bsiMVY*g0+ldRSTn?Pw&8wqHK0c%lE?3}&O;MZ z_aG>5_NW8YFVt$@|KaMpAKCufuWczxQfiNg)@)0t+B;TKYu}fc;$VKbIx^6zhL=g^+1)mzmn71G&-(i zKi5|Z```T{eNgUA_c@m2Inyl${_)3taYZRkZ$ic1W6RT)H%DU&6%3qaeaK%avklzO z5c*w4yImcR0W8QvDVTZYO!~MXC;gi3DXMyuFici)3ggG)LYp1t^x^57F9<(ZpU&E= zqN|&JZ`CtKd_0sA_N^L$?Z+D#W`3zsakR=3$};MV?ey4MOQKA9{4qVt6d>v9T&`h( z?QaU|Ip#HS3tcFiwYDYif^E939?QIB-OXUJ3GIJ?&P>tNG&Ce}O;5eZmpdQ?XBcOa zXhr!wkfp<|tBZ!VxXq#8c77Busk>Kk`~>?iFn1x(zJdy%9v8$d6_B}NCFH|MB^h20 zXrM6ufY0_^*o?A$rb}vGjWuFIxvO5kXs4)tkHH5~%uoUsyI@7h4>{~I_oT?DD#yd{ zjfmr=gcJlW2W2O?lyg2= zq@D8|3_XrNAM?_i+b>;I$2yTd>klxA9hW2b7=x_YrpQN8mY~p5z`9^hoeW?Q*&hgb z-oN1rYZMvhg*=K`xn(b*dA3!P949i!*w0REbaDYq9u64)#@R#hqNpRqY zZJXfQN*fw}w;871QCVgD#mk(a&lSX4pDd+XU-cKY-`FOVWL?BU6EyW{fNn1IJhpdh zQ!>ZTElj;~^0Iy|`S37HJ@JzUDiBPi;HIgv!$DE=h1-&TPH5D`@WlRdhT0OBAN$g7 zKK}?s)-7epze>V)#)JcLokUFY4)5jGNTE)VLHkbGw9S&Wdaslrppx^=v zq)^x(TKUWjqZ8aeHe-gAiYHKl0=%SuxCj2}g%|XN5RhoH_?^KX{{gQqTEmg5Aow*+ zk#3jCi?b^o3i9gpJ^8|Rvv4#`KG)Gn0vDtAWZeDy*E ztHat$dOUdP%%a>NJF%z_Z4OTxBi}Q|tu{YQYLkAS5^TXbrE&cXSg-BtRPnv(V-@IM*`^w%#mR3%I1~H*c z3i(T63+k#0sa>aOk0tV34V?}&rDGBg%KkZg$w0q({{^<#2qig5 zRRI`7-EqB~86pdsmj?pNDM2LZ^EZd$t=pe`>&i|?EPL%M}FFO zu$NpiDOjZ)GNB3XyZ_nP{(R_O))jjXGq0>e3OiC1ibT!LCBin5(W7>D?(OSuJD6RC z*c{Je{Tu7*lF%4*|Ae(D>CD++U-ER2+c*YSNY}m5eTj18lem{}l};emlsZ7|BRUG3 zUml2^9oVW-8mszXd!Htlt2ANarqX}=T*<40hZBWQ-g~L(G-4!fugZs=UfSX#s<`^H zrv`D~V=Cd?`Yev)xCCu66GO6MV&Wu@UTk!@tyaH(C>-ufhNri2 zYrboQw-^fDd(V>$vPQPwk?fQ5Zg8lg9&PoEG$!18tu2bZO}Q#V_j2SMf?4(N@bJca zA2CP0CEnouw3S5Jx5Af@E7S0uzr$QRpkl0Ty35*DGKeX-{db^mf@JXa@`9rdq`#^+s~G*O=VpI|n2BO#Pc$FXlk4wwn?r=pOO zcdj;$MLIC=Ij<86saqe|8!(4{cRUqC(^wxrN!+3zU8J22!QOth1$~x1n01poL!|Rk zXYZ(4!Ja}QaD5kZ(=%nl(&KM*N%8Ifkn2csG6UyC=FGYp5@3yLW#OLLr)-*2z2kG^ z>%Ti~Upl-*KO}f6=4bd<;qo6u^Pcgg3`Vu?uEmPHKHZZzFR=Um)Bxot>JB-CAX&Sz zuRJM%uXAB^MNeXu#x2Xsbqes5zHxas*W|uAu=wgLbm()iPLp$U_de8a^@QwedIJn- zz;r@JLcv9mc75D04~lL%F3xntQdei!vvqO3RgkwIryrqvru&@h5Lm4?$uYJyBj~^p zy9Mp_0uqBZ3k(I>RMm)OmH${+JPyuq3R2yh&$g$Sz`_8ynMRJc*(zQbd5bvSt0N#F z@(`+&d_w&8ck!pd=~o2_3yCSo;0jP7FTdD2ZagZdnh){?*?^o`3)LNs3KY4{l6T`i zM(8&=@j%Xm5NW)sNwZNJ@pDJvcOByo*|@5+@(;Hf4R`2)8aaS~!QV99KW>uhdwu3A zZr|eP&wTu9!zrD|X($;t#F6r*NRRCclhQd^H;hf`WIy5P%JP1p%SLauF7U=js66%2 zBUm48S^lFD?v+0PL)*8YC*AeVN%G{;K4J@sE-{}}U`;#syhgt1HT@yG!ZZ`#Liy(t zS4&2~Sjm6+2KG=!2p_%2+a)sPKFxTkC~IU!neFrLj8rFdJ$b*YnH(MB?B-SH!-{-a zc2|oMsA*CV)Zd~+d;f#Aum|h4pChIC$GQ;0j#*>}csElbutE;OGVYH{PtA!|E8e5u>zhHi$TMmr5byu<9 zkFjl|H&<$>%(;3*efn0F9H<-9Y^vg;8>lEyN^GRGmPV85kXUNJD(dRIHh4Dp0p>|r49y4iEOU9i^ zbmfLGq_qQn@c!eyh2SW@9{7kpC8&JEWR#qp6Kr^^tht2^xh{F-M+jd313a4T(!fmO zZpFK+UUK1zAFjz%JficuTh%WgUbmONA7#Y9cv=0)RJ0034adyW+rFTtiFCj6q@OfA zdaRM0k{tKtsQX^_xm$i@`|m-R$yZlhh4;BiVTC>jbWkd9;7MV{-(uA$B2Q<)lr=CV z=lemeF(U}e7M8DH2=hTb$PpSM%ZNtyNMwp!{lP1hF+A)d#=f}j(`9>ACoc^5vz`{c z!ef_<^M+xw-4`#Jyg4I#>N_> z_2<>7p8u@!9~*;js1FKShg%bdt%zK2D)qs}3v~%bF&qVk>-5#4oXCAmqoi6(+1@aRrHur*5sR2&RFpRq%0=`?o4S%(6mA+IH zKXlZRT+!)74Mf`9p!lDFqsa}5a-8%YKihwxRS{jDp`r4LdgZb0Vh~u`w{<(6>^eoj zj+p^<6^A@!o$BosCf7qp_1X{o@Jfmz2-Ab`SGUCkm9P199!$5%bzN`Sqaz z6$SgwyHhhRG7mMb^=T9)^#4M3i5j#}pTE8*+MYW4NC*Pxx%!4GC&(b{%=gMmQ;?k(gbTdql_=T4JSom72 zmz_jSJM-qsUS}QakMG%r&jrY~i;(s-34VHNF{G!o9#{84M?0q7-`L~n^CXH$$CC#N zHxWtdHw%KZTQBzctY2BZOE~a4Eq?q62KqvFO31s>`v%sgc5LwRV?1DeD6#e2?&*p6 z;~#8f54Oyb=Iu!JId5t8hvsIqBM~#-jiXvQTCrmP-SNS|Z>7l5wPNh}Tnr!bu*@=* zI_jYH_Un>y+719=xRBRg4Y}h%m+-xf`f&$$$vvK)TcJnso;+W2G-z~P-;+gg561tv zg7)fycGPfecE`g6vf&@+o z#}{H9a_p309P+?pCuI2@b?KKr)|1b4*d7@pfD#EhoT%#E*rFZqB zR;dZf6w%pYenL6{ty~-@mYz3HHN-uB4u%n>XpOI0+B{zj0gY|usD!_k>2Bnds0-kJ z7ViaX5n-YY@c=xVVDGg3G;`9|PRNwwoBw(g(3#vC!{zc?rwo+JXC*d2~j4Adq+zP4hs#H3g z9K0~i63F7W64SBLnH%+0>I^=7bs`9|IVKYd~i^QX&FLiTzmC`h%w*Idua9n2lGuyF@0Wq^*m&K~EA*Dx#pQHXHBp!=7P-vnRE z&%U#TZIZ;&iGa~>bG40uf*B6a<#VZxIx}5L>l4LX5N9E4BqyfDnS`f#Z25L`CZVmPj}}iM|NS;l zSY!Kb#P|5wes_TiZQ<95^U7{Se`%!o@9$= zeSXcTHvBQoS*!A^S)Ssu;N}p?JUf}ldfu>ToWVgJgpHR%n zpi19;P&QW@Hs~TQxFcczIzx1wiWrC%urkcByp?u#0%qU(A=;O+JhJt{Pn2UsK?Jpj zZ#m{~tSpZ|7*|uCX3IJM3{N8x>ZR#*m_kR}Qx)k8*_#Q^tow}0FZ;mm8vOz`pWnpe*Br9~p7H;89i=5&rBkDORUM~c;Ws$Yc zZSRdJPY7c9;x;_YHIWfve&$#mv4(yb{@ z_wk&r$#knmhj*ARD(qaGAU=eIoFC}5JLh=GSRZd?G-ZxZDsO=EWh+jXKwju@9)tf~g^69^dfXRBkEH%-vqgfh?hp@_Xm4m`WOyJnu5+E&iF3H%l~Y^y=d2A z;36ms9tdb^T=WGTw?u-dA{glCr%d*D$iLQoShA*^A@@tBFO*uqMq+g2uPwht%XhWNB> zt@b}SKbwxNegoMQsSfoP8`ub?SI2XHG8@T$17j&LeZ<=klSNtVMic5p$1wG^ya{gW z{hOO~y_*VpUc%ZiRp*4MqudIEyWCel<@oh_;k(X6MApkORoT5AsC6s-h`n8P@MDR^ zfCNfy+-=98k`5tfz`v^>6P?x%YDqZicLDD)a$NFN>uB9kLgP)U*EmGw#ih8tV^;0a z7tiyC+5cMJtM#G(OXa}i!(7+aTiEDzw=L=^AOkLZ_&+#rFw#a3h-o{{~*L!(~s!T3!t4Qlpjzr_-TeG;v&p{Mc}N+Fu^;mRp1 z9olrvkzVT>L+h$ojbQ(#i$%3{m*5S#5x%p3qB)28f2zfdomoC3YC)of5@c)w`IL{3 z&s-3a?+QcTJZ9RWr8fM<+DpeIxLNd`rn5G;wnr4)t!A(0;zi1ytX&fU3Bz7X2{=^I zgO*Q6oI;dOvYuFbR}e@CaE4P!Y|aIDy7{Jw_M)9W{B610x^)aspwzmxN=QHBGUA2F z5(i}+Go7$A<7Eb*7ds1H+E`XNXMSa2L8b1*&o|g>HekTv8gP{={02lOJa|ko{d7DV zn!670;vCEL5p*Q*B?s)Nz`weDW^wqQ0k#q{C1kj9vRMce*Gdj#!DNhZOZU{&n%4OP z?3nW|omjC}2&f6V|WT59}%E2=#s7O5#M_lpNG zXDOj?v2ByBDbHMTeHb)yM@BTBvqv%|>iGy7-)c2ihEI*091YbgN@<1u)AIi3TV<(M z{umFBkBD&p*0yky8GFGhHhnqzQ8*&c%^rRqb==%X!KHRb+DMIJtOY>-@dkVAlb`FJ z2H2fk6QUXFi9-W-8xeqL=+-P-D~_?6rg@DDNTA0bNWack+0|kB&O5Ip;NJkx_Niuu zy}-X``Gsk zzR!Aw8}zL5Ao&9~QzUY~OdI9^BLHDk;Lw;LR|$Rsr!34Cd(zRmupHmXuRQrwu>-k< zoCC7J`%t1`o|pBX^vK4|d1nXNT^sF_fUJV&I(*NQH05()6k7OQVF1JC z9aC*}^{FW@kNIiiPEMd2W)xWmitOMSKFj%!MmeKvk@JyYA95jtf%9GLU|LEqk}t3f z$0I&FKSyj`ucqKsKdV;&!&E0(vz3WvIV4URU>&GiONyRYr^-D`9WXmwOyC7$YbB)= z8Xrxtg*(&0VdD^-FUl6?1^O;%U(T71FjNaDv6DgwODapa0X29$UMRPLdO`7^Ri`pG zh;3SpZi_i=>Yiy7a&{{fy4Hd`J7c2tpxHk)&u)R=*^J1~6A_SL@5R3n*}hDQofsX- zRt5aE-AaN_*B)kpu#_wN@@4d%?-z^HvI*PYw$A$DlE>2>O>@k+V5kwr)Sy*agnveI zcboLL-62+g#o{AHwpFsRQoP<1XigRXdOW%qnU#@@_R}AIYHy1Wk#TN5LJ&#hij_uvGcPfg}W9Ts;zHH9gl4 zL-sX>joQ>19O>VokEWPHdgdysZaTlLmQ%(w^}9?NqO?-OqV6CHWeh~Kgwh)@JOmeQ zQ;nG-WQR(C2#?ER$QQNM>JQ?p%r085=(^QTU53?2c|UoC}c{Aoy49|bV& z6#lefelKt*%1LVL+HOt}d#JGVhty0;v-BsK68B}JNheoXh z^Q(R>c%e&ch~!=alv(8L(Q5{fzO3;h)nu z_0+G9=J?OJ1@cjA^JW|AOraFew+lq-?r5K_xioPKaBG4cYJ3k_b$TcY>>35W84A)S z#;PMW&;&HkZK}}b0^BCYNo$N6KOT7wm;y8-3aC+5k?t_B3PGu#EXx^e^2mLJfB!0b zD&8@{^o;=>&U-rt*kv^bmKPeVWtrk{xLOnQy-9o8KSZ-l;0lyKYm>_o)TK}=v`t)S ztLEw`f;bFx@Hed|Qod}M3K(F7f9h&%k-csCY=3lSOl>DuJCM{X)5arBbKeCU0Trad z#4_2UsZ@We-m%!VLa=kv=^adn|7RICtWs8KyTy=)JdqP!Aer!FU z1yGDXV0&I-Vh`CrolvC>xre~$9c%LYEB`cfMiE{&!ew7mAO!{4Lrakq2~t+?`~)=S zc=(#LHx-)BRRgqd&;u}bufd>|%8t^a3XL26thwh2th$s{BG5aiaM?bp2RB@pS~nCV z`jT-mYr*JC*a}*@q;zkCmmQB)HWAr%%P$ZHej{sibn1%yOjokJCLc%gc{pE$HI-r{ zgxsj`0sSqBl+pEW^;C#&b91hhZ6;^dDfX8l281bb=c7U@?+{7U4`%|&m%)t92@&#% zo{4`FUF4o2>;-u!k6celveR*THb%lDZf}Fj=&Q3Q7FH8HSb`3|pkz`>4U{Zg4 z3TcOb#^7$=5#72r1pME|YUg2R*LCy3Z%v-Xp}kq#8R9^&oO=kV(rl~)8H70rz@V$3 zN)r@3HtdSU4cV1r|SNc z*7@8}cY;UlM~!PehLUHdDrw?7@kA@aqVD|5DPX8YTxj_MD`eCr@T7L~7fA_V~Zfm!buAOKtcAQ$QQv!;;OF`PVY#nKpi8MCBZKd#t^O zql3L(1|ZYX3TClu2|T(|p@^IF*cy#`JC4i0N4@!F2}&eAhTFZqEVW}hw2R%f^%2NY z^AWn^dQIDPiec`{?s_LG&M1B+sDc>AF-BS99H%^yAvw9q3(Bdk3ouj8EvLu5vSd-W z)g9&d6gt5II2A+*wcZmKg1v+VPTkZDaJ`)ZsT&udrk*CRfio0>fgPlFwGfyeMC61! zD*RZ?dT+^G0P{*__OXS;YLpHK*S+ULDbZrB{AmXcdbS>`v+YPx+mIp209I=KdATU{ z5k=T+=IxsIk0SoH;A~yKaRcFj?dlI+Y3|rF!wm-#lFw%tGaO==E#p{w+Ua{kWve^l z*soSWmneh1b_+P7WW(6*o*z$S9iCnu{_;uix1r^Pb}e0WjUIK5pKIU}!9AG@;B~Za zcX0pffXqDMk5Yqp7DI23VtbAz`EGd-e9c~bMJg9$V$yj^z6vL6Fc9lXePI<2lLgHw zs)#KI^>pr66~tE#Z|E9hki2o*ocHxUrzz6!ubl0lYz`$0g4?ZOeHsbarYd0?4^W|? z%dN4i+I?}5!I?P~L5KoGKKkSC>|GcQvF8vPbWz5)U4Po0*y_j0OX0Aa4Nt-CSyGo2 zU(>#_$%sxyTL}$@4 z&M#mu^fe-j(JmFwG-bk%Kj!{^7FWo5OFPEq#pc0^90s&;e51R?DDuzOHrw0kS;_d> zY~v8aO(Dk@G{-Kg8;7ULfg2UcyntWGqL5bA#H=pIDRyA2pfPay9LmP@V5BM8gXv`7 z!2F~y(6M{0lyt8An^)le@TqJs{B7!?pRUXN(Ai_j;KSnjN{GwM-G9~F=!N7cS~;&R zi)VwZ3Do4#*BL0a_2fRkTE)4$sn`0rs@_Jmc4tIp)^4WMSCB)fMvSku87iRdhQLK{ zSp4%2@hi`&ezl!`)J7wcUkjVfb9DZE%G#hIdZ*|LsBNf+SGod;c7oi*NfgMr-C#|% zR0GjL-n+ew9J(A#Ogz}u0$B+4`hG`OF2sM&v`{+U?Ae6)nh#$ktT2uw9{diXpEIZR z2kqIM$G`52O38b!a-|DA#=kfJ5R*EZp1;5`#U*oXlks%#>4+W^JNMC(08+L$H471u zlmKdQu;DptQIv-kF;qLj(%HfLQ=r66M3&60a8)&pKbO(mM?=f3fIz za}{+fj_Qxlqa-8#Ly<&spdRU6ABCWs{m8`152N*Una$Ofc?atRHZ!`Y6qudVV*R-n z4likY!D%WrRi*k+lXTW&&~X7*@xMmjN3DMe#i`CjZT8mXYZ$&>)$A>H?%!Q5`sw9J zQYtpboOURklL5&s#d#=%d_NW}`BhI%3!bO`JbOY0M#uT;t+pu}9)^k4@!(r4pFT0G z9_%#YXemKRja@G3eHV4w=c)Oc?WSQX@o`7v`D-o{m4)k034t6SIhs@*IW^CuKk24p zXG5$biK53xQDrP(resX%p<{9^Ac0;!%D(RTB{)z|pibvpo=sz;5c7gCou z;A#`R#-r43a2Y@znGc^DoSlZz%N3Lg_c4Gz>-$B_1n;e<5cxS$_(gjiRIYWuit8k0 zn@cvOmiS9re~2BQ|C9)rwU=Ki5?-sd-rKJ|RJ%BMMywBUBjm|BHOiOr~%Cy?ZN|;d`pP0{ZeP z=u>6u*K-3?uayXgL=cmY`d!ZF6t3N_Tr7`=Lw(d?6;CEOdb)<}{U1y09l8aTS~%J2 z(bm&3`|%w{)8+*9>*c5xO==UmHo6?C%?IH#CY{BfE_ER@u{D_Oqh=jE&=9l@dKb%! z_+9y^gAtKDKq6a{)ZSUxuveivmI?VgkLZB^6!LH8^=|1P17q&I-+y)(vK`=I<`9^=EP=+L(l`r0&El7!tCNCRLO542;}OX1>cd#iwnR?}FR z$}(RiIq#9IlI(@&vuhnOaei=NJJc5>=`HlYv0I=mC#%I=$fxT%*`DX(a&1Q|pE!v8>G@6&TqFKC)@Y{eYMsS2!U(p(~T~ z6S%5j7WRvTY{u%(<+5qCW#~~qXS~h$SDk5?i40F47?~8jOQbB@p4oOF*MP%u*}2K_ zfY~cmm~S@aS9L%#pe?cV$HM85t#I*5ZzLjVCg6nQcm{zqN#PLWK+6BH$Tx4$nTmE=7K8%BEc=w=P;7i$P!%)9QmrkEoUQM9oc}7b+$@Nwjjg=I^<@2?dX_czdvc5T&!3(w zpe!rW90~G4H89n!pcsD9CTzTHrcpB7iVI)>judD(w6Yb{aXh zFV=e*t(kIdtbCI@LbSF`v;bj~6ur(a`rXwwp+V z-T|ClQ2|{M%mt*PNxL(HvN^1D0yHGx(?mG+n@6$d+>T|6jw3)$PG4!w&VN6l>|Yo) zK;Or{o{H%d#5Oh+EE1;|phXx(jfp>goo8S-alikGE)7wrY`o0ZouW$ny`Eej$59b0Mu-eQPZU zhts#n^lTW<%%)at| zzb6CltLHmp#OG?;zq)D(M?`b`vp1mEa{bp!>{V8;%y!MK02oAZ6bEeV5h1Hz+6`ON z?4?!|syGsul|KTN;ft62ZNM&lekZm@_BZiIP$#uz*cu>(oV+rBhQ+xj{(@NQ*TW1Ya1bB1{kx^=zE#) zVHkBMewMbwyx`Vi;|w+`pdzC2r8rqzWXWnwdv?tUn0h7QA}aSc==EcpoQsaupVfP$ zzYEo}sh5=Hj&ERo&&JROW7*%Iae<%@v2CFVv0hGh0&a1-sy3_sAyORQ=Z5qx82k&R z>8a>l*{u?{ev~R2{<)-nk&CX!x_@sz>!WIjH7Q$kWj~6sJvU#$mFn5mVW1H+?1QV^-{NXM$h*aGjV`${h`~~Vki0n3ABXEWAD*94Ux*S>%grU*o~N7-zut-XCb9>& z!)1k)X+UUhSGOhXyClxFr6ABUk_B=;JTtoU(b&O&(BdQugEe}WRQn@aK6{`d`EQr& zgkw8JfxA!Hb~4cRjZ{Oq4_{=u+;!BCqoj(&dERXnNdU@Tw1eyV3Ou;9fd)`sbyzTd zS4WC{$;(hNvzefkH%U_r=|1n^*XP)q6>@XV)>^Gy%=0>VL<&4lpgu|fQR7ZqKFL_i zV{dHk2;7B*`X<+=in8QoU!?=<9}pxx{Eo1mYkz}m)RsTXv@N=_>WWtxBnZkRV)X<@ z-fqGSCj2EWSY_$eGrXc??D?6Pe^LIsTh_bYnbaqmw?B`j=xL`Z2qt4~CLxmc%xa`M zF3LMdahy*gCh+2;JFnM(5df3{B5C0>_BDnnpe^E)m;1sK^D<103#Xu48sOrX@NX$@ z5z}yuZ)CsLRve%f#(`@3<#5t^5~iLcnCGe*xmn<4A2&Lz7nI^MHcqs{PlhY8pMQvg>X4}pv1Pjyaa ztxQ3p6V2u&P_y%uYIcae+l|xFA^>qy7;F3!7z!@CRONIH7kJmp0#r&1Xa=;XA&8k5 z=k`x3FD!K@IJ6?k6BA%WY?E2c`VeqbctBaLZmr#yr_Z71i7#!^J&^!CIz%)RDS) z!B>Kv%Jiv7;BECm%W>7)keAp0y?mQ%u}YQdJqJs0zL;qkSR}==sEXb%?L8=w$;|}W zMyL-p*mt$izxf;ON`6sOtbX0+8&ZZba7K3Y7eOw3?&x& ze~o#2ocj!>9!0cp+aj@mLM1!iph-JwYh>f+-LL)49B8${N}1ppbJ5N0T+7Yt=qyg^ z6<=kMrbn>3hX6(PeTQ*_0!=+i+E%aYPa5j*-GOy}IoI99=1f3Ji?7`Gg3mMB8auF)}a8LEtoox29zm=SpQIc=1?H>f*6bkwZb458kr;Y?C zCUVjr>GR|rNJ3WNlk?j5EgMqmQ{67eOj2OJ4TJ~0LP|_{ERYD;1hciW*fh5Y%bgc3 z2)UgUrUVrhnkstM1YEzI3bZ3VzW7^vTqq&g%B1)7T0Mnpzp_=@LCCqTz*ij#K^+=( zn8u5xWhIAu;`tt`e(u90>Afu}-WRg}ek!89T~`3n&EA*Y|>!m-`Jn~_vXR-#EJqi?m-7om7$enArU{?T;T5EU9o3Ozq94%fSQqd9 zzn-Qoqkx9;TIAbC2zGXdKj9W=z{KCA5PM<$2cdBlA#2U+O3K=8xtdivK@Bk3Pic=G zNX*a3{}NA8wB(8#lSM1OE4RMg_&L<|mtO_`dXF%d*PVo@tv1cGX_O<(rgaMxig%=k z(6Crd_HKzos-jE6(m4$GJ#V0v**yFbS&80WimiS8Qm${wNIy9q;(lueHPWlr%5|R0%Rnw6DZmg-b+tvc z@f~FPa270RG^Ut#3MJclEHoHT!CXuYb^*QdojVY(@uhT2!o-`_OgW!u#Jn(!VC?D+LseQyQc-G@atvZ)blDe9$n>L#1ilrdQ{D zvn_XR!v@$H8wX7G9I);&g+jIP7A*p4zMSg2Cqq^X%$8_edn#Jy9jW3rVaW0cU#jXg!gCz84j056j5WrpU@a#otbd8E!0(?R`{nrO z04+vwR2-D~@*`u(;QN2M@T!K(h%gHqojzQE)Kk%Lp;4h=^Kxp**DyS>;xNFAL^?c; z3PO2?hS3=FR<{=4Jk@YahVL;p9qxbM(bUrBvh0tUre9cl(PnD2mDYL@=!~Iik_55T zi7ClRF1f%7NukadB_^gPm;XI>u!75Dh0hs1&c_5=nm#^#Pn@@vdZD!YNB9A-3EM-} zjrgMW`ouW*V-D{@ba_{K^%FPLfwVo-jCe%C9h<9AFef+ASilPeHK#E}jTD$lAyXc1 zy=v)dec55vLH5^w)H>TF{t7yIU$C z1>0qXD3IYOkW)_x-Xr)MJMK-#+fhk7yK*AGpKQMV0zc0Zi)LJZgL$bu7*ivgQW1kp z1Wxef@wxSXvguoy&pGvWFY9v6izQeooftMzYBDK8XZx#hSUCO`ynM^@=NB>#b*0LE zg!hwaZ8Sw}S@DlXNo-GTZtlob8cCI)6mA?!WQ(}!Qo+TnDQ%sIc@{aVxOk*_f-HVQ z?-IaYOc3l|O%$+^T>0D%#c^2+tM)5_pJ~-3P~W<4CNNooyDi52ye?1yM;C2jtYz1JKIJzh-&WNG!7o ztk+YrsSCUtIo6lC{VzZS2kM&}nNs`-n5VLA;5r$)R58^PFi*q%A@;ElXGgPiN!HVk zvH&Q*+p^56$qi0BRd;i3X!A4TSAg{iLD}gF+9K3AT$IUQ&O!n^VpW!b{iNbnF4P9i$95V*7gVfOLfA6BRxQ%Gn` z34HKq;`@_!qndwE7W-jz;P~n^9s7s(B(CS%rJ|{qe24%{+js}$Fn5RBx0Z14T*il5 ziYD@9DH4RlR;6rz&OlO3b^OPp(RydcSmb2jZfqf6(cLQ-|ZT#19C zeLSJY*I~0bx=n|LR(gDs1E<>xj@5t5q^()-<%S7IArN91IA(>!AbQe-|9DupR_WBO z%S`KO32g*`HE-JorglEyNnk{x;an^^e-E`id+rp@+AWgt8;y)*O^Zh#^Wv7!AwhFR zU@9>}?^`4lxx-n?xs14=LOQwCW$c5Aqi;j_hhYVJCxzva|Kd~rSA>EM{h(yuAYAhS zWXJ1D1dh;u5o5Dd8|K}}CC}rJxTza2`iAB1sAz+z)cT@o0GAF8RHEKP>6X4HgL&e@ zoY?SCb|A>g0qR}anfX0{KYmt>9QbXb*=&e?Z{s&B&5d&^ zIZesRng@V$uK+!P5{bNpY0(b)LK>>Q)6h=q{$lk^vBln~4SOwZ5NNx;BMpyp2Kldh z_w5UQ9;GX&=_ISW%Hk>oK^`AzHI=Qm*^(#w*rj6%`!9v1m&f)4CPTyPk>{LD1K$mq zFHTo$E8INC(TOo_oGemwdX5w;cM|#^2s(U5E^q0^N9x(lm^1A4y&OcQMv`p)JV@39 zd_PASdE*a@E2;5@vn^CB-^5U&RGG0b!LRnEcF`37BXVWhtWF7lEa|JkH)@JHy|;Ln zqB-~c?AnX^6ZsU^7!d?N2mjZvf8%1isut9T`qFGzTT20PG;q|Ov-ax*O7fKZ`I3EG zq44v*QK073G<1Bq?E<}@>m{e_A*_2X5OLZwRs6(wZPHqY21bM4%>-0(1GD9R>VdKE z#SwjuH`y}Y1qodt!~Ti7zrNZ0=Klvt4CTtBdV_3+9VPU-_q$E8W&aypB zVLgZ3_xj759Pp^wWo)q?q?M1r;A>xJp2tCf-c7nuvGVOr+@D&dPY?Wyv_`IJr@K7xVLW5dav&d6K18#O=jt)+ow^ZA z2bz14VB1#1=FIqlr858bK0?NS`jzVbUtOxVu<&H88z1#*j&6 ziV&8gmORpMXhX;Ow0~U1G5b9^`x(NFxE94(@Gqj=wJ8%BiaM5t7BXbicrW5ZYnZJ} zXS>+z8wF~o6i%nH`k3Lz=x8Hz`ACRo|Fo8^sNlk-)wC1Ze2#psF1XC!OW?h!gS>xI zz8ep@H)#Oh*~+d$KPn77P@8KBUa-4>)cEbsN;CVN~LK3&}>U38^@a8#^n%hc&`v~A>=y^y-~$7XYz?c zi%}M&7ZWLpmMPSGl`)Fu3Y7+7DmS|RTK*Kd69=U?<|F1Y~%I;)}q83-IevmNG(jaDM~P;A)5uw8eq7^UuDcG@|5kr%>$X+@s! z&@n?VdA2(6VlN3iLEu{osyyJ3W;q2HP*Epxf*kp>;EnysA&t+^mK1}&&=HzAb>kG^ z*(+_zWZ&b_gkD~I`IJp%t#*??%>yY@_m|xo^}#;((^sO=fNxT*x0I((JBj+Vy-_{q z$e%C)(@Q^x5{)Fu1;jH{r~D(n26O`Mb&-SzG{k*h*07 zpXlxu1a(5gQPa>u@Ru|yeI>1t#K(+V63OeFzFKK;eVzF9e;BZ8qQ?=ovvJ5TU+(nj za2}Zwj*bGdF{_RT+bqyeGiUuhjE>n3|JQpWY-#jB`;kIu6^~R(x}IPiq1Sq+r+H*H zm^3`o2A*UJ4@r$tSy4E~$|+TnbjHdk48-}it@XS&8m`C(B*-jtA1}Trr-353MB`|_ zi}&##2U=SXGS)?hzXE}*upbkU>Huvkk8hn4v_AC#(A6L#aze^G`OA0!i}o=@dWt0B ze=RB@-c==765}GuzzE6#l|fBWI$S8n^~mvPw4KsA=o3?P`1z000$*_j!vf_ariX1r z2Zq}of$J#&nexF0M&B?{>=%JGtl6untq&)c5F=^7Y}|xko%G~&tD7{5`HkgkXC0DJ z*_vP2!m(Lj)Ux`A{n=qXQSf|_AdGKInaBF$nY4CQ*+`_^+#$3+Pi0*Ga;g4Oxglu5 zBJ!rtig$K#=*%jA7;*7W!pE#9`wAon5T_SkwE#$&4bMfNydQ?Qlv8e+@-HAQHU>z^ z;@U5qPcy4`Pb3LP9Aj3j1wZuE^2jXsOrfZ_j2^0xWpjKg$?mt!;>IqOS{|PdOQEP| zpgR&*Xuk3~J4jlNj=t}D_Co|qWGX|6<2JNdi2^AP-lOiJKy$v(Rm=naYo}e(c+T>m zRl>f%p7pC&oDIhTg#{VY4a$avibUG&X}C@sPTz2MP>0 zhT${}InuA;pt1XS>2sc_#VX`9u$0dv0{$yy@Rr9+EUz^CFSR zXd5H->6uG%&sE$v!uc5|;k9D1HkMyJ^xTmc3kbb?)nBh?**=$Fl1JHRm{vCT73fZq z-R1q;G{>nn!3f$ld2kuV9p5vpkdmoPk)80#OEPRL^VYe`Xrw2o;k`MtXNFh@Z?=mA zdbIE}&mBGd`4z-B$cn*Z<4NvM&4I_W=|Ogk$%<;@4uKot-c}u&G29`#nKgeV-QqtH zLm(&EX#KErFWhA14f>D+&VekGHN`&-4%e?6+IGZjutPVN*6p4JPOZ+&QU6C5Y`qho z$p3*XR!dp$7MZi?hOTx%5+@CJhlka8AS|8pzBm{XL+yA|FF?xsTmzlx?@Y9zcO4Sq zwtEDl@t9vDaVMLX`1FX2dpRLLEn^Gw3X`+o+tF(;|H@Y6^f7nS#fr-@9?&Q%-UI2x zkDfZj$MD0b7S(!fRH@6SkSdMkmD?sRsauf>RsmLkXLp1`72M{Xd8`!}VNGFO+uPF` zXu|KZpuL;mu8zGP9vOfSv|*ne@S2zlNer5weh{2xNeLNSU>SP*QpwJN{`Fs~tVED1 zX=?9bh%r|J6YCSve$X17N1|`YZck3+r26Zs~08l5^?*{%9)u647Y*Won}V!1Vw zXKQF|f>KYSWat|C?U@@Ox`0Rvv%X?R#wK66!#O zY6`ws|LM#&D)YUjfYtBrh~gKTq2mACizyQGRI=?hE_#jb{Eludr&YcSic;F#R$*d} zHkBx=Q`V3m_ceuo&<4R->(uM-cY08hYxpPB>>lqv%UAC9(6Eilq+AUyxCa`H3p~Ty zUQQ_d)9E+PE8WIEQWVoyO2YkPQ+4KA*K0$tdMw{d;9v&{!7xlLkEJYJ6#gQuP|}r7 z5Bl7M7hF498e7nEr8VovIq=y}Si0nO50CbnA=n|Xp`Zc0kiOy#FCOQ_mxfe7#nc?T zQ6YsgXeugx!s~5Cro^wMF7EgE)g|U;2%qsC@<%it_DWq|oojF$*D8N{}IIIi4{=GwRZV#QM3c#!Yb~3n?1&I6nmSm?KK##NWvrF{_y8;72sb@a7iE& zOWEpE5{X){DP_t1wOJYd7=W0|byg!bw!9|zP>^z@a+d^bei zxUL$4ILEV0E`V=>;X@0P)Tsx3~T!Sy0s$Gf90B*e}`9-ggwfVjbUUfz()~~Mz*&8R&BQ* z>q{({4Ps75`Osreb>>7J4Xi;mFPihSAYVF7|7;#cJ#^H+cASC&jHE;dhmcqVQ|abzig zWn|8)eGHMt_?ewy%85!SFQiQoalBO~wZ`R98qgfbcPjH%L}AL-m_kIThe8+qq)Ma%^Rv!rh3APoQDr{K-soYJ7pTBr{9Xe_iTl4->Khj z_WMoM`y#Viaew{iY$YeuqLdWr7=c2%)|Tp1U!QDDt;+YfvmO&q(cf)`Ic|SM*jfdm zVAEq5l+Nk;IfKP>yqv?UxE!|5E=@3 z7TE`SxoN^75+rEZ5*~qIsd|B!%0VPqv)` za+f0Ciog7V`o(SqSrv+GYau zi;{t#Y}{X6rXPrbtnPy3!)awH8k8~BBr((z1ONT@ZqLY_^nNb(Fj9|D0!|0fIu~D; zjD*p?Grbf0Nq;9JMeU3u<(Jx>?>LS&AWbCzKA_8T4{o}vpm&Q^S`_RtJLw;}5rZMY zlGr7aR4q|U$Gr{z;#4ES`~#Z0dq!!vs!B)blOK)4gw(NEZNkLqUhU4SW3Po;^#;+| zIFa6{)=Rb;@IK*r!d$J4y4i>YR9o&0Tjp6dtjhRl|i>wt+hQthx8r7XsMkmWXew3FtP| zdup-+*|sA#=IxUp!#1&JW>-mGXE)*4lMZ=gDfwm|IQY+GU))B!vl=@WWIE6m6e{P8 zc7=&s^wz14a59!;x3$_WDlRK72F5Os(K{)<3=hyK?>@CC72{M7O=%pu&RG4%OAxKN zfAbIhy3izPG8K#zb8WojKPMB#^eg6S&G|vI1#}1yo)wXYr-wjd4#M8Oj#wWZvS5d9N8n=$*7k$on=`ZNKtW(5O8u@(jrO2dvND4j8 z)bnzwT8#m+!#++^A$qGy?oPDoa78TUE$W&3b>uX%iiZ3-R2v#t7`1m#tm8=80u?md z{K`^uW)je zZ>X zrDvC!XB#)qo07bDgkLD`WlCNVbtG9SbBbWpJxMz@w0=?=nS)tRK0N)PQckCzmZD(C zxyJ*I7L-SSaPM#2Uv;(AHc~3}m+$ZE*pQ>$Q)$Hvp53@_Rhpcju2j_;{zK+_N=Y2N zV^TWl!Y(RId_TQty|*ME&=is;^85@STWRxB=u0i z$*Ry_gR(yOAa1Pl89e*m_8%MGlX6kfq~(Qm^2Q>0u8*x&szI7TdS20w=QQrgBQoezROSfFK+vg40^oij}Cjm1bssU7rbprVD2wbn%RF? zaIfy(3)jrCV50GNQ?ps~+5{I8>na_gG#B@=>o=)dr&XnT$zS%I6pJdniu(qms}hTV z{09C%aR1?NK(6b33QBTHHlB;kEeFA;rM#JG!!moYA_Ko_LrGeimb1%??dfnAZte7`C6mU ztJeq%%C@8B=WZR;W!?J(`_rMVH_5vnW=RI^o;e4Z14EGk0b@_d%7ibUy-;^d#@>TZfj{FDvL0?tT(=eyO(nV&oNuM2zBpg(o= zon@26!eHm8ypwmXebXHN#R0Zh6y(IW{R^!s(3sL-86l^WUIM(Up`gJxz~9tYtHJP> za)Noc^K3J+kXSGS(WpZ+kpf2PQis3@xvFgwm@76&p31wG!s&6`aO1@ zR*R|eR@2h`ocK9W=(W&DeBH1@)(O;bex23rAcVP5Yp0?t&fr^`)f=u~p{pt+~+dLcHVBliIoKNQUFI4fI^vJvwA3Rf=Ru_n3dU4(yllr@OdU-^$NQ_e|6h9-RkZ#XnE3R66N&j{{HZD{rv#!MM}C*jHV3Yo^EFF%|GrTHpWlfWL; z8>vwaWL&M}2`$*lE2z4Sp2kqhY;Anr+*rOu8x_V92Y z5k3`(rLHiUvDlGGcKP3%@$_c}2=Kk3$+n^PCSgRK;(RxsZtzrzb+Zn%n?xmGTEjTy zi9n?IVV{FL+S=TOfj(9UH`T5H0F_4T z`>*Mi{f)>54B%L2tAxk8o`)&$X%{m0U^(Vc)deFLwpYiZWR64|aZXq0J1V55Zt%C) zxEYl1ruRt!D}RLit&<)Lr8EHxBulg;sC3sNq!`~GNLMx$w_udP){LJ{;~$%Sz~jQA zigXv5d);5A_Na%jG^3spyyU*;n~6_MRt}%-zgMYLXb+NJATm@X_#n_FLDc7&&xk0D21~teAskUWJj^d?|ji|V^$Uf~L zb^TIccVMeYkPWx!2K7gvz>+xCRCe{;t^=hsr(nvCl2CG{H>gU9DMmfz%?R3QG(-N* z6Dp2afM3ro7X7@lb-c2o{lIwzGG9JFthU=N z^A1yfoPf;9I-D_E@=45++A{?`MI$vX4+P_ct*wgYD0ax)D5dcHY#PhP{(H>8Zr}0n zHjK8sdr69-kq2bO&OJjHra%O#rFK#Qh@t#76zc?=3$ra1;`l;0dM|Gs8F|;GBdL0m z?|*(`yx7?9Hz^FWg&`BXNf1gnw*XcS*qo{U@)WD3l69uR30j_%E0=hCQImAcgHPL(zeP`#g%v>0CL;3U=icw79y~O z68A;CLTj`|3ptKwwD=#59km?yKa}xZi7`v1T>hkiy`HpWu}+mnYb8CjrRrY(qf2%F z?O}*tPj1iL=IsmK%M><^ zVrsyEU1Tdi&rY|k6?w2rYlNSdEqc9pX!vZVpmYzPaZY??Gvz%Dh)@c+`79F?cf@)1uu&Ep|WXk}3m`UaV}+EUZgQGpPLW*=e08<{D<56^u+U#Hc| z`D*{|bp3KhRNENvdq-&H5;mB}SiyAa?{}qv!Y9^GmPzn$fcvFZI%DLCK-OZ#&W76T zm6>`rD61Iz(vM%5*=9_JXEJ}F!1yBxo+d7XhC!{*s>M85u(b}lawDcKX-bW!Nw-=O#21} zMW!sCC&f3~t1G8{TQAfhSkRC8(=9qncWhZqg(0KJUY*kN9r{%}ZNMwhnQzJPNwUey zM5N<^rP4{pxYCPn_|VhM3Fq95)3U7kB~EQzT_oD*f!FpwfKStG8^3w`I!-O(Kqz0m z-)lk^9aZUjlhoGHRb|B9-)%UvPG(u*csl`ys>t@c6tC|#p_6IJQv6%9-TfPvN?2<^ zENt1Gi;w6_bszqw)?G`Qy)SnjwMEXeekbc-#Q=ezW)s8K*<^_0DF@?ew9m7QnZK`}-V^Fu;ux;s^6E1=|I zPxs~A@mYqHt;%SdY%kIuE2Si%-cdjU8O-t?{SnUf%2$2mkDn*!LUmIAkF2}xS3bF5 zLNb`F>4g-U8{+9UiMpn`KA)hkLWv0XE5m5c~vpi#+tR((p8(jueaDwh0PQh#Zkp zJBqT4M6tv%0;OLon6b0)RX<<6vZrM!gN*218T@S1%R!=`IGG0pOjwj+J}vQYqDR6} z0yj=pu~udyj@sp15ffiAs3H7PYjBf!`0H6vi!q(8=3IE% zn-rCOJFYM94;TWKfbJau8m*rl;~V^0Qhe*>nE%hDK@pzYsmIT%^fw>uW8Db4ihez- zIrUn7@6RKIb#v~PoH9CGnKbMlnn!NhdmO)ZiQC<-2{)oWaiMzJbaV%-PXZ(Dg_8>W z4G3OqVtT2gyzwDZ1&ROXRA1&lh#hUhLK;067Gbd4JBytzS3w)hoKl#CHgy41i zG}_Qw&6McqDh>CTrwpv;C^9wq{+%@K>EY?utm~<{R*&hLM^G@@8w*vqbale>jj9{ z&hN#=w{;PJ_r1vl4o#muw&t*@Il_H@H~ptcOyn@mT8X!dMDGb9Q1McWZmsGbDI9pjMl9>ZCkyaf{6&{KKd0K?uZ! zvX4)2IvY92L1V#uv_Fjmdm~*l5z1}n%DPH*GfdefU!VHU_J!(2fM3+pdZ9gP=_w!$ z`7sRx+g*Ow);;i%Vr2B!{IAC8pQa4mkqtA-3|{r7vWvU z`_MNxO9uW?t(t%t=N7TRsx&}^*FhD%$r(l6;XAn_aql@s9~2(Lw;0ZtPl;A8=>D9g z&}l0sl1vJ_eJ$AM`|8;l05!@#pGCb&j_^xc2jFwRPsJu&hO^QVHK8LnHr4;$1hSx~GW+NY?YsTWfwD?16uN z2d1g~(7QGQTCgr-0ja!-#gC4csF!V$T3i+g!fmYOXrO3tduH*!)6%}$;H-34H(p%n z@%3Z{a!4BwU6fWK19*vSQP`#7#D7aUVW;2B?DL)q^9bj&?Pgu3f`j(=4Zu1=hmdw) zonw^+*Y%3nH082$Wvkt7^%yHwUjBd>4E~5J?#mdPy*%)#4 zz4z8F=}J*aOr_J{MTxl7AA5WJ{l;2bIB4*WTdCE9ln{`zoEql(*Tdbkh8|J41m_w^ z#Cx|~BZYFg2Jf|Y^i+T0vAD>hEFxRh(`7(ml)BBu5IN2N0SXMTjwxeIW?=;nUm0})$V61g62Q=K*)5Z#>Q zPq{YCDO^Pi_nndstsjFH6_ZKSqIj@EKkzow~`Y@j6r2#X##tWS+XN-$jDy1@4D1xyET53WC zmm*vhg@|2zct>DVUzjc`5LptB{wMYj!_KB~g$=`#v&;)U1%sy$uI%8{rNn@S@J;`RwX zG-$e>^!0mE|AQ)UwsK~ZiWo)Y*jdn5{1YjKC+yX&^|<3PF^{3Q_`}ifqZSUCFw?K6 zUWGxcxLIvNl12*$EVGw}@q%bgxI`zsJ8pe6vv$TRnDC%t%64q;>0`Av1u(I8mQpb| zIF?@#+2P(*&w1Z+MXi9AmxFGt769Pf4E${H*YVr{Vn9OzyJ_Ge9?>9mZ)vtEU@$OM zp{(@^^?Lmni2HwzMML>&mMB;7nF3Sa&!1Ye7gfs3{O5^2T(PZIQr6!Z&1W7k#RQGJ zIwjp>L&j1A7j`K+V5bFqy`7BBEMB%tv~RUfan)s892K2TPFWHVy8D?sSp;;6=pCR( z_flNZbM=Zldn+cSP%$Yx>N;tdU+fSELvCF!h|i`0@)J|?s+Te}{VpQiqt~DAytAie z`*E^HQ&NT21Opr2(X93_Qm(W0Y413j%P@y3h!46L53|ATUGy1@5Lu(M8>qyF5(jZkn%|2AK9#Wez$w#Ef3PbWWf;Y&CiSEx=d zPtZzC6dKwxgod}5v}zGY(kzJKzGcUs$Va$56Dx20)}7{$1lVuEfH4-m8IUdImh_X0 zj-_Qnk^!p6e?PR6RL}wTno$S+-&;6PunE~w$zHGfbHa5zdq32)p&a^G%ji)bth`)L zXrp^y64cfGJDtSL6xO3q?Zfc4@Z;F#&B%<)ASp74_E8yaglmMS!Mr2*2ybzbQ7?`1 z9AhIzR`D<9>f8mTz#B8dVfVQu$&M87N-WdxMO`P^7P4u?L<=ITkYCjQ>MD<4FI%n0 zeGXVuYLVIh4aH(@AM<~{)O1ojyQjGg6tBR81yZqV zx368}VHl>V5Y-?d9jr~#&H3*Q+w9-kuaY3+CruEolc0!Gs0btYGQ#6g(<9WDp= z;hlew4*&7qk`g9rEVYOT3z~bD&AeN!;Jh3F3TyV^vO)R*n>B?@9j7spZHj>zAe*y5U0~@^>m^qT=rl-vNoNZ@~J$Lq(ca&1xMopt53O(SMi@<)z9x z-guv)3~-GWJrSPn-VeXLIS>s><&41tO=>`H42&MG9nLiX8`+Qk8o{!H%s#= z{{Vy=P@Pa(H?Y&TB^DclD>*c-JW;|yl+2YxvUVeB3(XS;yrTCy_I-9*zs0)Nl^sd(oCHU-M_&oSV3X%(Zk<~^<`bI#5mgu{1fAc_yPP>zJm6G|BBy%LSN&+7 z`&V>Pu&9vLuT)y+Tjh!N2J3qL-?jhp8`6`fR-^4Yr0F#fbmo5QdfS%CZwbWyDa&p-EwmvNle(iPSCR^7>n zl;mqKEF=fD+qq%qG}6<_j?IlPfeu$EgsNaPOL!Oup|&Jm^LK#|+TeGqE{3yzy2mSupu@trA;zIYLSxCj& z-`anMQ%+qr;C}YbQ>YUfFpnKrK#3}>A0F>qBQfCBw*@<*`D1OZ{SKN*0!rB?hVRnB zwHO%Vnjrls&y65XpLwFl>e3Q1g93jMP+xuc4h zn9vVtdHocmHS#Y_n7)3-)HJ;TScMM`TMEtfWjRY-!Y*Ah%ierEhKe5^ouOQ9ujrGZ zIbc?ps`-F+!h*yY#Yf7sV+NoxC=6&^`Uq@8h>n$iAn^B4ZnHNgBP`qAWYvZcb~IV%gbnIOms(9#x}@=qL}7zRV|UU)FHo`)(>v#HN%L6T|0#T&o%amW8O=q&wJxi zwq`jLt!@uVA5&mS80FrA`^CiQvGS*1SV*YZ+JFF*5s;-$e3b#3=-o~N!vDH!=VGbdMQo`-wf9+PGs<;(t|##IIl zHHkxE;u*ciz2IETBBw>k8;MZ{>m=nL0WM|e25ArHx+r72A8sk|_aaJjC8bL1!s`$h z_RE*=8ERCX3YSnR_`tBE!AA7cgOw43Ymv*h-%4d2l8c-Vede@&dQ0b4+Y3PFK{fIA zO6cBy90JlsuTg+@3mjaR$8@y_;eUfRCR=)g{)Q73z-JF8U^b52T!?I~VO3Ko-fm_g zm33mQb1Hv!$OGS6B{wCp*c}eL<6kM(?uod}r=96PoAeR^+TpA9Gi52IDBlPaD}es9 zs1${Lqp957ES5G`+dCF{xLU+rg9|LNWa;agrc(Nwy}sp>-yGOUb9N-AJHn;UU?qY? zzJj22Z#L(U8ZgAI5o@4n)66baJ|VI& z8h^W>-nlpoR7*1l3#~pF{zDjC39EdvpXNQPV2c^Lc2o-$%cz9J3pdDd|KYH4gIl!; z&~@3~8Q2h%cL_Sdr#4a=Hk0N61)YOJOFts(DkRaXo~c=*tSYHjlXI7tThlEM9Xr;5a)ZxI#HAvJWbV9trS#P3=kRPf3H# zM>`)8W39U;L>1Gr(=IOuqb@r)xTwHg_5^*k!&e6TseTwvz<5}SX9(ue^{TNkez2%YIypp$3l)Vi0)fc`L2eSXRZJ=e1F~E~s zz{*RP0Bu*L-P2pXHuaHC#2sl3?T(AEh$XlEn^V36^c`qD46WgS@2lrAh=R)#z2ZN0 z*3j4*U72B>nA`W@b+{N@8+%13el03>2aQiQ91My$I#k6qUN%-ctPT>Dn=X!I9?lMy zIt1qfH}GfFD~mI49DEo2@O8R>H&su31=daRfh=`dg<@@()_|vMnrj~)s-#{}xSvYj zNuq0Q_-nxe{i*h>jI?8;X_&>g`bP>9vof}wcv?|)YPjDO7EuR&x(q^pKnzn_+4%gP z@52urz3T0rYhIwD;oa}1U|He)N@7dmef?1A|NlA(VESx8%JY(l*i)!3Q=d#XYG@sj z_wPbK*8di38Y3=pA-?#56Mi$0CNlAq@6_znqyCb8&Y|D-dtym_mdXhIrlj8VyQ=$> zL8|v$lz5mJC^F0`<$FIjyoHKGRiG~uFCGc!jY8E{%Q9)YNC1=Pc9!o}eDm;jWQVcR zB)gKbCDH^aNaPWR5^JvAu%|qmW!)H-3FmP(IA* ztJ3Rggh1@Auor1OAa`FqexZ^dZZ5u$p}3pB;ND!GQVZ;(Ps)c~A;cT`tO zDrO(1Vt;+l5z-NWGjK6gKTIN89vt#dlI(JcZdpYCCz1lAo{F{KJ02uHyChit%N$#R zjMlkc-2*fhTcz8&cY1G4J6BxaHGj{Xxcg6Qd{ocH25teuM$S`7Sil&rJk@y5*JeGt*#QUw(v42$obX!_OI6^?VIUH^Sif3l=6wQlkj9qSL9J=IwM>qdaxB2QjbN8IH5&0WxN@i$T*si78 zzVOK%vE|4;HQRPx%lO*XVh2W0K*&&7lI69rNk)An@oQU~3Y@c8{%pw+0vMo(a{u=T z7z6mo@A48$_QK|evqxuUS+l4$@`j!DkGs2Vf#0%j^bgh#k69AQJ(oOd?g8emRa+M7 zCR@w>2Lz>F1v%eaZkz3t3 z#OU8lVC-xytQ($WPG0O>9+`_9I%H$`CF8qLdN1epvq8E3cHw>a3!*>Nq{B}Bdmou8 z@+lSsq%Li?j~>J4=^uvF#MSgp&Yew7ub)hs){e8qRj7<6K(JPqqu*bMr8RlhCqXLV zJJDk-TstOM>U7Zo$(0;Ln>6Q~FRt|J;YOj`OE7^a-7=UTq0t2@AXo=mo32m_=E)2` zLa$^vaM*&M1!u5DeMCJ}E6`={gd#MuqQ68pr&T3aQva~1OT-VeWNzbK{l-`l2`($= z45SQEkUTyV9`&&ynmb5C<*R)f11V^3=^jtoXZua)3nK3m-q}afPZ)9|8`~c#Ha<+2 z9+cL-8@m?;ma!nb+rs+O9u9q0pcn?_f)aO?_s%5lsiAad*`2F!t>^D>`=$G~uKk0) zCn+opcWscG@f1mzXz^HUlIM5fR*3fh*t@8s46Q(^S;G5Ywt;xU%;J0wvB~|q_s9|V ztcdP!2_?oXddBu8X6>RLC$mnM9B1t@!8>aHF)u-9$P`+lzS@iVZgj_yzPF-E!=&9sBZe`Q zt02p$$J`YHLUGYrSl+6GJ74#E$lLIOODrpUFi?isVl~lMcG2cnS|IuN=pv#9Xg+9mCrez=WnAKSpD9~(X9Qd1YDrW?mMbS20{ z!TT96OShkY`@Ru)HY2qsX3VzKlj_|gH+*1yF{>vR>S^rtd!onR?_R^{Bq1&)w=hZ! zByx@mz4EWTpyJg}ONRVh$Ow#-ZhrThMh0_eR$J|IKW%5gYWpCdtQn0=I3E2ynNL6F zwmFq3^gjy-=xS*(p0?$T@Rq-Xo;6?E*ITLzoW)t^05|C2`JUgWr9kA&A92Hl&NduS zd|mAZ&u+`j!FxFmCI0V0?x`rB|2UXs*tn|tB6wqnhf8ee?h0V(exzHpL?tH6J#U(9 z8lLMN>hUml)IIoY(_2MkPViH`dCTjIO;f+MkYahlm-s40$iWzwnPsgGLOF9^WB;f8 zu^6=#S<(Hta8DJ3t0XVhwr_gi1RVss*npis3tEo);S_kUaH%uC<>}30-Vk_itcGl! zh|@y@eGTp?cv$q9F)ziJx;9~#E({4yzP65%#O4nA7CkEM-967WjzeT72$!ch?ZCC1 z%CC_t^%`mIuE?|(gO;zfGk&O2cfjft;lK3+!+zxKv9ZGyk=X#ppYUC4CBcezDba1&}=LYVueJ~f>DuI^cLpiE-M&{pKLEg&rD z{tL4mlXNlrJBax2UgVW1ssEgrv~6bCN$NTay~=ep`IOyu7n;H>Y9v|4CX4>m8z^b# z&a;cTt5*fLHU3W%m{-1`^ajekY&KS+KDeUvxOI9!c9 zQh>s(iAqT05%Pt2U1yH+8O|*T&O3G>2z9FJyS7y%IcB5JWvh-t+@K(j1;3{FbQQ}m zDwrcOhxmKm@=#d2uKD!u_L+CgQ*IUOGRzcA=2Is(S_Dp>{b;hYK-W=oLgLdBi7?|f zL1?Ew=KHsM>QHEeB$Vlwq)@q3NI9GTS@#k*^7Ul&Bp9;;!6W7AVut+g>JBq}>z>LG zdo&7MGZtkDn!PtyR2vFuC@AxoG`-qupRhP^yY9qh_g-Av^Lio5oFfL7cVr~hIMVo} z@wiaIWnSAcf1ow+u#1H;=Cq2ZH`Mzp*HFJ)hlG9UPCCpU_FfE1km$%GxZqFs8Vy`R zBqMB;@){hgZ{V@S_evp#el8)X8Jo*7M`g*D{xm|{o zH)~K>8^jyHxNV)%?K>s&rjb~V(o{`UdD5Ac07Q6n39eA{mOL7FdGv!MtYzO)XP z?jC!D`Gl>R4%TWO%&1aMQSY#GKSO4y4Rs!=p0GI$Dohr_NFp|_xT6(+CK6hbLQ-io z*&>c~hG%4#0F2IatQcN)wtuW|l4q&Xq2`%YPBvDXmSV*N! zX1|)8D^_U42o8$a%Mgt1=hPhd*#b~Xi3@++q{K(1D~o;aW0m^zXGGv=d;qYO<4N)J z4&poAY!he`wDvf`=yba6RU&87z7l2uj`5<|eag@f!%0V? zNEYU|ad4?~?;3TPp?*XF6vwl!)X_cP?t2)Xo7a=1Y`N74SU$~#c=N9P9hA@IAql5^ z=0?r!`aNpqWqVGW_u;@e_QCtSTGf##nGQ{;#T<~L{y%L9_0J}VNBgrj0_SG!Ag1`; zVn~+<3c~CzNOld65JV|$F4P|p=>&KAn@?X$dRfVtcUP z8&=ffr4R=+ivWHXPD1NL=GkFVi+f7vEVC{?=o(=S2kV^QxJ=j?sID<*QDg5~3I?hY z9wu4&-;k31#gt{@%U(kF>NK3AHb=xZ8tkY45>Y%xCiF}Qaj-o%xU zK0tHyp6vo$gt4#3Hn;ohYQGg`u=UP{@5sCbbllZ4gTXgGgi!9X>Y}_1k!HZH7iia#ahm9;;vHwa8_LX7XKM8 zh>eAl(zV7|eVUX5%dbYQAz{z&8Q&UavO554CPxf|^Oa4Wfr!G?X5*9RN%UkDTorQH zZ$qI#aZFJakCt(Nms%1HUYiH(!l4RE3N&D6qV+OZ(7f<(SlCS!p?@w0=gxB>7Hj&a z4M}%qm^mmm>@6L#LY>7x4F@Fw)Fls@qGi2o$?{~Q$e_Rcx&rvef=%vc!Nc@2#xS3B z6$2F|nvmumv+@scq30w)1_*G(plwcj+^$P3@ZNKKcRx+4Y3rws9iA?X{iLCAw$CC4 zCdeC=BhH(WB+)T`gF}6MfGXx@Fu8rhyX1D2VfxCJh9GGqd!I^?| z(v#NeON#*LnEIsK-u!e%{^0qQSNP= z-rK0#t}+luyLT!04h`@KqWEA&`pCvOG(f37Ywt%th>(Xfty$gTd%f*0=o+3g}?*Q@NFR ziizecqVrad(|Uu(-b4GfBn$iw3Bnyo#PHhn44P%%ILElJ8JE}}bBjas(Zl&^b2Nt? z+mz7juv}w;m!)uUcUo|GQRtb!mUZMpl6U1bMK4#+*}}=;j#Z&W4ofnm&)(k8YrAK^ z26Da6A8F3*wqTS1({^b2L!ni+us~+NT~z}XEmm$wTOEm5ZL}|fpfrlB4!CT;MFG9@ zhVGm%9~1w-4@Y_e1Qv9%+69R!A!|c)rWGxDEDN0<_tStXEp5a9+b2#ypJ9mV0v``AQcmWu_UNL-g&}nO>iFRjZRt>Y1b;x z*dFOA^Nw1`M!162ya3RPlSan&urGyrB*U>SM;$pmu+Ms(8#~6-p-OvdFB&A`sv}~B z@Yu@dDu@{q1IY5~l@xUHU1AnM*k7Q{CykDszJe91SRJ@Fjv2s=V2(rDdce5UZR-IL zF1iZA$i`Q#Cooy5-o+a~IA0AQVES+o4#G;)*YM;;09@zbRZxrfPc1_ z((f3bqt)OZmwTWQ&KZ0CU`h_4nqtt~8QYd4xZ}&lbi9sg4X>fSy_k*$ltwdNeQ;wCW-&uRD%GV$O2l)!8iBqq)RLi5M zX8I)PENqGHyW{%HOPWFjUSwrJri+{ujrKR^Ha4JpCj-@vi~X$<@i4+zi{%FA=F=%S zAPNnn4SdLDQBH%`209#|)jDh~34pH&ts@ptP6_ZVw5E7=WoszE|YflvEb{6W=RBNTAh{L+%wnzE?n52cXL@RuB3v z>hC>a+U=o4ZCe84mJ1m*MO3J42aE@n{)LmYCk>;=^fFL^8a2ss)vY| zgwoSnmWFC8@Wpty@u#;3adrRd8U`(wey!ea~8I;$>LMYnZNGU)sW?g1?mTN@z z*t;tm?kkOH=FS5S#M0U>Gt&jX1j>M6)(QOhwDH&IX4tJ_z`ZUHI2DPKj5&l)!sBoB zJB9`*Yy={$)nKC-RIF$sX72V4Fqn4rR@us;Vw;4Mjp)@DFG_;TQlKAK8dqrQ;r~O{ zS-3UX_wRr7q(=@UhazAAA|O3rgrd?CA}InQEixD}deT^gz(7%?L0YI%!GJ29FITDFMdv*j-lhW0m2c*^u(6UxcS6GhW5(-s)zR9*s{4qP+>C2xtI+ z>a@6Q>6|gah(4?Xj16Uq^yzlzHy7)4bUzt+cWEl;1cV+^oaGGp zFAgK3!^BN7&jjd^Jb|QI>Yy{SW2ihkXy2AQXt~a7-dcV;pE9xJD|oe69glEj&0tZ6 zS{*FbcTo8ElFow`fVtj12WIM2%oOxe4!Qe@O{oy6E}dz;$Pcz&pxNV8{3>@W5Nh7L z{z;?dFsB3^)ok)DVp%@x4a(b;FG<6Z{q1We-3Ao1Pqs(wTpvQfGET^p%CD(Da+{!O z@=S%J8Q(C$BEKX*MZ}vm6p|8dOkRymOxE(9~gvv$%3ORG=vm- zFUg*bJyqgy@L~LYZ(Bl4eC^g@^i`T&jX#7!6OS6jXg)4paqMxkl<>1!tEXhW@nzvo zm0=k+O8}nTGtl&gHz;=fd{N%{Z2TC6l)Yzbr@T;P9)9 zbaV1)+nH<1MIRl{T0D4XF9v45suz~=iOe)LP#B)Yyg@$VpBg12PMmu@5m}9SCD<Fy zCI$;Tj6*DAX3Sp!ul}>1WZl5sIWCjnp-X%)P=6i%y~jBn&W{o63Gp-ilE({QXEWfC z;%oKXcF$@k(WYTdY z2)V1?yO#O2r5_V6-*hCMCYL)EzJA%@&F(~k!X

    8x_Pdmqaf;_ds-liUu@IFqB81lD9~HWr0oin2;?l^H-L}W8##1xMNva9Ytmd9vDa2Qak&ar zdc<%g{?crjfjiqa(y&H;=p=ysZdOJTf4y{XIKEeVD!RyW=NlP6hw>xlRgt?&AMt}z zKtChR)M+*UQP6uY*(nBRW@e8E@vM~`fbpGClCiX=gl=O9JNi4Wg&9Ma(0w9BMQx>06lrZ%Q^iLrdzrM@s? zfagb;?1RJ#YRq85&Z?8HYzz%<3HmOjbwD-j`VA5YTlHe=v*Fuk%* zdYYfH-xiUG+-}#UC79LW^#wvlIx*t>F^U*{isI=}o#KRlB)s4Vps<9OUuePY=K zfb=z*$B={RxL8!u2){1E<(eOHD5?Z1ebB2`u6r_T+3egn66-q|Ih!p*fNbaL9o4w) z(qXNaGb(s?7Ivv>d5`?HeGfwF50+On{5mr>)GM`HHYzRML?E4OnJg+g+9XqlDa@W6 ziSvl*OQPK_REejdG3@sRu81ua)!p1~a8Z{>i1idLLP$6nM_sV}YQ_b0lO3(YFut}I zup20q2Wq1Xfyn6gvqq&~c%J%PTr~7#ojr9;A+s1=osQye{uum%+-#MdFMY7I&>$(Ah9Cg2_>VxM&!2&05m6 zmzVXTSevCif=L{LI>*~HZ|>GyY^|C=92hr0l?cE>O6Atso5K;;z;iM{I3?nJnX7t~ zg7o4<7V%>&cf~AM+erjg;91X(|GUQ#Uh#H8#jBg%lbTHv>(O3`%h6)vD#PZa1B*a- zuvXoStzaQJ7XM&TFg>pqbja8)w;6rPg0MI_z9$M?6No*L>=QsMd#x+62an4>mvmprWmZ}}qdJxvw6j1uG}`$wa}-j~u_$SfgoRQC0y@Vq}2ouATB;B~c?FfmJ= zZtq;!wNlI*nBE^Ntzq$`TBBr5qc%J-z}d$KY4<{OhC4qWmuAT>Hz z`Eps@8n~F9xO4JGgSCj21#QD|sUDR={0gsN@^KK>RE-Bf&VEaF7j? zdU48^4H>0d>9YG znq7XRk>>f{aK#S3lPk{<;Tud0@IN>8UMB+P47Q-s=>}wPzO4XQN-BaYtsLo%w_}eLS{pnXuagN`X{O!_0hP zK~HiZ_Pf0jM2`Fw>>~fknH-(c+V||%iNHX@8zLz+Hx?MFw$r?+P_zltrSH~w2BLV^ zdek6EOB0Y(CNM{0?+LcoP-=TOq<;EuODc-*y;k5P?5)e+5xR@mC|frUrEBp-izEBG znCHn}=iwWM7)i=IP*e6)2HB_Wn&Bb`A0dTX+}jOPS1d7iU!NwT4pvJxHy56I#u_3< z>j7>|Ejx2FnFkw*07#OlQ+_)X@$6+e7+2ELk=|p3h|>6UPJctdJd66rRzLC6lN1h5 zKW4vZNcklw_iEnmo~XO%PVX1*oCKZpLVX?9h(lS+ZaI9)<(1xg7oG0C2B?m03VfpW zNaa>X@F+9(6qB1053ZfOX7uL`U~GrP%Y{ZoFDqabg413;Xlwj(HW}dR{Q8EHHUt}~ znPE5fB~R2@Up)j_Gj@KW;b9XFKuUcwp@b5PZZ#K3%b47i4F<6iJ^TA+3S@G-M4`4O%uDFLW6i*a9>e|37tc0_I+B>|9jS$NX|_FU=F5N?)`qCsF5TSK3*W(dp#YLW*>v*pmOh_`9cd9X^cY-?`yRqVqWB!h zA8CJ8jejP;P$m@>*_hD{24Tp*mrx>3d(>aN_#T(i_>r$a*DGV5ZbW9H?p!@PV{O%k z`pt3#qX_J(N;Yy`U@F1eEgWG+kqoDWn2O(dc}F%#lK(r9D;RHR^HJSWKV z@D1yT=G81EJ50FZ)D{3%>=w9boCW1c&r6-SDAjm{m(}#0 zek^o4TeA{56W!N)H1Y0rH*XsI@zF~77FP`W+lx$cYX-G7Ya*PMG3utx0QNBI-0dkX zy&262WmT^k8nx%Jo$)@2)i(E}!6$uX^GtHJ6V|OWyvT;8wbpqGlhL4comQAaO77%bRX~NG27K ztuapZitw0PCfujonbfB>dXf;Aa+>8_aI>k}r&dN4xD+`BdlOVzzaxRB*-zw1%(lqZ1M5B?0Mn zywZAUYK0JhyIIQX?osk((;a{iuW`e35-;m9Ye6)dy}lC6Hj8apr(!pzKkNwq7Pfacr}?vga3xd8`5rM<|UmuknHQ&m^?f6vz_kcbwo&$(i3o;C%PHmRdYn$1KVB z!f?f3uRjm0osVYB!-5%l(v``TO^W9ZW)D35^fd2W3X9Een%nuz8(_VY_9>aeZIZzm zN!Gr+zC6rw{ZXi($Yb4>fg@S#D|2_llGg|eL3x;!z1dTM;lL{i-~L@00I?BJl}HbW zkd_V-4Z1_B)WFBr8j0iXt|vn{wS7@Y7jwRmn8lP)pC@X^t|1yyv*)fD0R5^PzOE(# zD=elcXJ|<&oRh%vwmTsrM4zrR2YLiTp0T*?-Ffl(HCVE z=qVx`bcf$eAp7+$o#x89YSg5bM|a4)>-0Jb#)@orV@frsSX3KW;ht z6wWt{n7R$aBzPwh)NkCn`Ll6F*$Xf>V5cE3(`6iu9>EJc8e8A~8b<=RZob_I^mgHsS@xckuLe`GkO^{s`6aiO_-8>Nfx~ zl$gg5GNOl#S3h84C0uRy)#W#h#;g)7e(6sf`5mP8yiulm*+2dExYd@x%F8xFcP|>` zzEqNspjf-{2(Xsyb@Q~&WY&NDsXZQ_++HO2&(N&7PA!$|47`DyeCJNp-1u6Jyk%>* z7gxQw;-D?&m9?#u#8IB>4~&CZzdsRTgZPSakdD%zR5Ud#l?Lk{!>_i|2l*MZB$gv* zTv-104#@m5hyceXC_$)AFGnM{weFDliPA4kjrXw7OhtTdy~#k{sq^aL)hb-%KwsRF zpzQ;QnLb`)#)%F2EDN)T8G{4h5sQ?^_X_pZT3)ocY?wbFM+(z&?e2$vvXI+lf3qZS z*MdCe8NSV@5R1?RMNw8Lb`DyE+JHH7MO>8TyLh~x+qT8Vm1g9xf9a^yRoj?+UdUJT z@%{=h^0N9xv!2Xn-tys&@*mpa`#)2zDQ>#|r?H+MaZ0H3AFG{qtMBhTE>%Q`y7D%Y zV5`(4cuqd5fn8lJeW|{DrY-yTT1&1D`jv(4%pP=_BEy0MQ!!v*CMFATKn*gC1bDVT zePGKnL?_fdzMgTPtKGhcqpz*t^AOl_!!RBs-Wn(1C+^O*BJ;WYCaj+VwV|L%N?8Q6 zs)~Y9Iv(n^m}ekU91pEwTd+MTGQGA;PA>Q)i`cr2^JjkxT84Ec!=hUf4SXT*F1{BW z-Nc(-DUWQpm7S7Ue~R>v2BP|3=}@yJm_z8LIU$mh#~jZPcLSDa#_j?P_sj2V#axa| z9CLxOAX?VuQi)x;*l(e7E|6Pl)6ZnFg6$>C1A2lO<30(5E)UyOl}EE}@kF9U2)=FU zzTwyg+O%PD5X9D7;s5;xwfJhs{>4WulZg4v1`#=I%4;VdVinfdsHo1pc6+6vtAW02 zK*{@^52nux(+d*mr3Ew;gM250dZ0q&2ugdW&JJIBjeA-xQ_ZCshMDJkD!Xd^ZxHE9 z{a~p6qrKG8_sbDZYTVmD?^`aKb8kzPDa^eriI;P0hSey{6Rv%iyoZ+%oKQU}g) z<(%84+R>C~)A8iE63J*t9&d5&>dVo~tpzA;z)B)2O8QhPTq!|%r&yItb+sgor-UC-X{_a(Gd8P zk~RP`vTGDgGj(b|Cpu|B8A5kN1{mxQ`7FjC1=F z2XzC+*r=5k>sLRFrO-$)Zvymdp*^I=41p`rHQ;!ULo_B*=g|pw6!`@3{3MI8uC<1l zH~pLe@Nafi4bQ_|4r$tzf5nuhtpGOTYg4{iK+Zje?(RARmof_pxZ|}?I?nD=2N7hsaFUU@l1tzGL+>0z5wJElESZ19)_=asZY@_Kcb&d(zpyy}qAdP{>i; zuR2ePcP8u7BsLMo<$H7D;y8Qhf(su>{q zY9SA=`sK*iL);)4Yk*^Y-NZXEp-kz}*6%ECYBavAkSPN)9vNcOg4}d_Tz}DQ2uW7V z98FsG+T0BFQ3q)T$PbpGtV+?Dcx6y59aHx&&Pt_;r1LzX94#V%Ecm9ev)x6@B|av- zW~(qIq_geZmu4sU9i=EHPt^hK)c8Y>cbflI<>f|51g1 zbkXz>*Nqftc*J@#DPozP4lNP{Rx%-~T#6#;f3IHewKt-Yf4N2lSM z6U&T*TDYoZX5R}z9fQh(MwO*8L-^Jeg|3Zqv!kfc-*K2;z?z|x5BSmMJd=t#Yg-Xy ztYJ5zC~X}-u!tpZMFyfvWhcjy$NfK4yn|JVE9dkF?_+cWkFWaajLF&zd@OUYYgM>u zJGf%;yxutagx$t(tV`}ME^3(b)pFNir04=({%ud=iP+tu$0lB>vNZgy@H@j|O|EHB z&IO*fZ#1|?N>G{w6cXoC$FG(rTHTA^qTRIUncf$%fxmvNRe}4txSqmRP?udOdf8^l zxw_ih%k`>fZ-D=bN|(=}bfm09V2EKnBy5uGpA5;t)uo@+hK+SmdN+_eM{fK69A66? zEyWBn9vOffJWU&IQen99lg^IuH-dak@M_>iejWAd2nS_?QZ={E7BpY*NYY@0fUuSK z!%~F&BWeyCBhtWwgB5E6vSv=W{J|>?ZmY`!{;waf8&r91nc_fz2{)qe00SPrub~ zo8~}OIw^9=AXYTw6sTXGZ2jbAc3KO!+<5`!IzdlHLMk(NSLJr*x5o49Yk$7Ql?liT+}eG2T=rUJ>Dq{rgWt*SiHbkn zdiA_(opZx@Yf&Q?W-Uegu7!NL`gkzVZE_(Kuo>#4f9Xmsqa%z0LdhKkn!L7CvM8(M z9cwI#3p<2gE{uX2-w9^KvtGVyiBtp$yhEhxs0O}QN59vni(AzQaZ-FI7+xxkCH9AJ zE-%VC`#&FeI4S!MN9Ao{JmRd$@DVg{S~RUQqs{O4JWstL4gF7Y;gl_N_1?p6)rTY% zmCGO7+9x*(iDl#8BJ}J>fv6yN3rOcZDdqMVfZi~rcwTYY5QPTgEgifiU3P)H8i8sn zhQLkO$2LCy%_u}>m(0|Ijt>S0-F?enCaM;~V5U&y9$k`N2S?lV|OEBqxyGqz9DdbIQQV_znH_$Wm^lLtNd1Sih zPnQILr!sR}SBHGwy*h~ld+oY|qNmhj0+v{9f5pNl=`d7O7|Bry4tuu^VK&xQU` zK%IZ<3-WcyKW@k(mq0Hf0ApGMeC&p^=9=VaG$%=qI{6KHsfbA+b#Rl!`mm?})4i!Z zq<4i6#MpiOT>|m<<-(sD+Dbp)=3+Z2$%z&g7iEX9+f{ko&ZZU=T;wr_u?>%S{Ag+a zkPLJ7^1j{Ii>h2+ANw-QFmTx0!aXuPUH&}Qw=hC|#!PX8Xi#g^`Y{R&e|C+V2KF6^ z7I+LhnsYF}YCPAYP0bEj;h-|`t`exBX49I=T2#Xeo(=n3K1e zJP~4#R^|KaXuZr+K-T~C;AwcWo$U12?_y1N$dO+JQncyhr2FD6Y|Mu@l-)(uvK;q1Uv#hjjHY z>oK?7EBn+Atct3mjl&BO)Ud}zmX%kKfdpnQIWc#8Zl?94G$q*hnu?-1aYUn_5IlQ^ z;A$7B>jVWs>$ri2!t0b#f9sq8^SRR@FygCi&}M;ij9L&4>ZfC&O3S#rP+8y_K62>- zDg!sX6IeR9X;}RA1v%rdpboREMKB%qKyhd6FQxDxVtz%%}Zm zc!a&#)$)=yksWkVW*98%ol!K zH3b#GMU8Xs+6K#f>!A$u=JtB2$098f2Y4=WNA6mrUB$f@chI-poAX=nOArTiOKFKk zN6^G&pBXl}Df3z*wX}R~yWg6;S8yr&T|TWkMUyjJOiO|y=^MjEA}5aWZscoDjNdGz=MsqGscW&b5bgp#(BwGXif?qX~A0-&s-0Xa`lI3@D z?XxQKu`k}|CHd{rTU%*a@I1isjE4z=oJ@*aVrd`xb_w@I$=BTwXa1%l1{J z0PeHHa^mLT_TLlU;PFg6?x&;x14Xd@8jYoA0Gepb1o79Ll_=Df_ z8IS@7ZFzdpG ziFQulv)Zhjkyg$YOyijQuyY>r_yHL} z^a^kngue6n;Q`S;adat^W)jmTF4hb;bmX7mdtTDgg4`dMzVk|_hJKyHHyjSuyE>mu zog7CB5#qWFPHYY@M^GVhC|hzN{)7JRQXtn`mypj6N0<%gkdI z2+8!y)}p2*+bJJma_3#xfXs-)irDj=G)32Azu^YApZhCjZg1UTF!p9 zSh~&E`W6D=Iar(Z!%Sfj<~%^_X~#od z=PQgMD7*w;E2N)f$b#=h=rSuchtXI0>ptxq(!VR4lL8HFz&1u|A}`6$3brpka+EAg zP@@x+gahhMPi+5_dk_c3NxgBLDA7dMQvGuZET>x-DHJK~I$vBFX77Q7Z*z?tFfxgI z&jmBQ4h^(XBGC?jflBSz1~oiJcOAWTphnE@xk74QPbd&VI%H^;yWsOYNCp=7HrIS- zIg91j?+)WXhN70hCY5ZDJIR)C^*nmvBmmZ>9HQ0~rz|z&z9b(Y*;p6_t`zxhKB2G`+M?g2@F~0=L;6H6c5yVg1x-JnAIjC-6@)_HIAY zW<{GYtey0zo}9z(oAQM`l|O`ZeUf}Tv-rpqyY=$Q4%&_(QCm;xR|)?)a~oMN#&Ivc zp4nPHM{8*?1liW!j13yhWA5h+R_>P>q*R4M30<{Q7RR|Y3c_&_2(Kt!wPWJgwO!!8 z^W!lsgRqmTUan1U10nsOw{5{!gq8_>u^Tvpv&+3yA;M2fkZ|R-& zl2D$-^#tn{1S8axNv4{in>vs z`7{S8BL!LAVYved*>0f+TI}l7nm%J%!M(6$*c|~^vU}noK+7h4Jo)`{U|eYy)QxcM zx?t1#@`ikB^y~Vl6lP$AgJr5s2O14GloO43 z+tQAqs+q3hadyn8#CL5}j9(eewXYIr=G#VUXTLP`HJb44M7o8PS$(g0^!HLmK$1pnoKy|MoE`q7&edw z4th-W`L-mPpwh+Y-!S{%tc~+gcGg7q@7!p%u*V@Rp^vV%@u)hI#Tzqw=8lR$NHD$G zRhy6!ARj!@-Si+M@u?b2=(XI|=*YoibzZuD&8iS(5`pIJx_QNunb8fK>uq5lBgjF> zhLL?uw)<9=%F7wiu2CH(27QuOcF7>DCd|6j=-nodG;zc$bu^+|z3+FM`j%SMb1ud9 zL&*X9S%2^B<6V%g`2e!f11sUZg4?|#b1gv6UlClg9$GRaKO;Fn)%b*3Lf`mkSxH7( zGI1Kur60|x;=b8@BrC)e+jY>&vFkhf>2-aCX+GH!*|4^L zLJbtpfv;lg_}Dxl&$q|bOEnVdDNHx{^_V5mB%or}cqKMB$dg~uI4HNv;*cJ>!@BI! z#7x->QM)Csmzh^N*R*z*hBci}-g}`X0K?qDqZV|g(`xTe1q^FpcLDom z&?d8YDMdZac#>-Y0t8qf*w3f>(n>})Ll+d%^8x?hj+r!#Eri~7f%f(Mv_kW@e+fi4 zsYr7K^B%h`={d4(-&uElz@t=9=VHk9Ul;aca`P!qHMgCviXgsT&Sc0Q;nCE?7#R3h z-683B4>Wsyxkhw~n=#sZ#7aVs?9!cn?qdBAt&kV)m1KxNmkCRxzBg{SBN|#uxciG^ zbVS>zYv$+6#IKRcpIXu(z29ln-**-Lj1V{A?=HdNq%Q>7V`Lae9A~RuarG*ULZTx> z>{^`lCj06&yB9e?y@7;v@w0;XT`T9$w@cls+IFJ~v*PM7I4Id_#H{~Rzwh*{=R-7J z&iruw>$%QUtj9CjlSntTA1STgcr|kA&6zpoPu569a8!1_sGy_c!Bc^!A1S9U`)efD z-zxRa>5#ddWi|c(Kb!s#qvpryV~6pt48w-o_L^SZWN=%hF1=5k_%m%I?!6R{N;D#T zh@UvQnLw<&$G5Jvy>Q!_obSUxL7QvVt(^~$Vgs_YeNz;F6Mv?X%F0=$hbS?0N@}Tx zA*K2v#=j8Lt$II24lBi$7$_97U43j<(?F5AS+!$&i`vn~u$cbn)OEY{w-D%LcQ;AN zv!GB{3%xs=*N}8Aan^YiVV>R(N!S&@6KAYWMjVjH#5Ts9 zO=1ZBu|MhgKe9zeL)Xi4)F}xjB?MFZ5Y;2R!t)!wAG|2%De=l7TAkC^{29u;bA$;0 z_wCOcqUf(`*Wvbn0&xov&M?JyKC;_=rEhsX5@au> z5~@iGEL#lQCFgeU5T5cYPg=q7G#{sE!?Tn4Le#uQYEWYeo!1w4p7yTRTz zFP?+hir~+nXLM0jC7&^IrGuEmco~uRo~m9^lNUv)cEuIutA06!hdTiSg{*GTCkB7n9&sq^;4LDR7z9$>n?{o{o3H`z;!MdB$(x52k_MVPS_mTk=X5 zR=1o-#G}M+sT@2P*kd~+J+Z&F+9?SnG<9pDq5`*+-sdM_(fC-Bbo(1=SMfn!0Y|jf zIIj@b;a^EzWr-KZ?_z|H&Ksc(oQ#8Ic2V{*BpIib9`lELhg!YCIP0w$nICDggy_9! zT+lJHLbZsh1&IiVqD#4nqYLCMdj46g)WfzGitX&ZFQ9&RxY0Y5pvqx_;t+FXIj{RD z{=36+boame?MpJYrKJf+;?DFi2gtf^A9=uF3e-7|epx>9BAT-rMQWm&r%2S%z`122 zdYVYK@7?^zg6LQQ^vL{izWT9*c+1AOZ&(L0T%H<6-P{&Pb(d6b#Y2;O7bw-Pfzz7m zLY)OA8FlFZ- z=Qw&g!?{uk>OZaF6}F=sOMw0mTd)Tlc>W8%Hd{PJxAH9@=MvriS+rsQg;s^#Y@0i) zK@qbpa+>Pf-qm{#U#16!{Z^tRvz`l8c!R()OlcO@>M$68_w{nzNs5g%s0mucU3sh# zkXOL}&0=uqAn#X^QlQo6BkB|0di>E+@ zfW1wnC7o>;Bt$2Qybh!Fw6Ao zsA-#WUAPR&oKltYKlheqwqRKhpscjT*RAvVQUX?{c65TYgXNtJNx_Zs@#_;se#Tr} zd908hPp1xP$jCkruCxVJeR_JJ$XU*XTm#0pkb5+Up=R>W=4ARb`p#}L+LAJg(wp^! z{X6hep1FQ{MkO1U_2{5&#wRvz{WM!+6Sn5VhECQnSbNoE7rGx5&#L?0yMV{^=C?>_ zRD1|w;uBYgnt97aj@d?DLh%|@pV40fH4;(h%L9mg%EP^4p%s7JRY5|`C9R{nucjvO zzRJYK{lna&F)iL{?iWS*O5%&cUdI3i$9Sw|9 zuzlLr#MJ?n6Sq3w_PgxF9=dkm^li_fr%&$IrY2kt=$ro;A%)#+IqQC)cRxMR+W>8{ z0Z1ZK%{%LPYXJ)oLs!nJO*mS#7s!j>9pl2Tg!?)?cEdS?My{L-#sfLhts`QdhmWNS50)Ap-lg688 zy|%l7WNhU8y5oodObU;@m>CBu48_as8|Ld?nDg&Oj3`W7TtuEpV1VKDIpZ6~I*WxR zARg(7OZBtQju;=Dg}{!vHRNk)3jK;>s?*RyqA|hF@)@#&TWY;^$YgagK^X-ZSM8(tyI{#H4FT1I8=}^ zt4t;b+{@iPNaJwGziS2V+jOAC@`q8UJxrN;v+ohT_o(!pB4^CS?u#qx5pMSB0;pSK zRS_C;E3xqV(~0qi#BTcoo*Salb+(q1ruDbohd)t7JsIaR-0NpjHc*8uoG+YbeIzH; zWL}+%q6-86?==Y%+%wuP4zC+p{?9hbj*O6l_>^ETs;zK=zQl|M?ENU!C)H@&rVwO&|dPT(sy=rpSE*=`3A(8G3WaO#9wfCjEio%ygkSwBLML+Nz}Jvs%ng=EDda*EZJ>YYm6XnX~_6 zH5|nNeV2PJ%$D0tE<-baww)$E_6yFvyb}Bt_ z+ac;!-Ew`dUk=7CW0^ZAvJdk({F6hJ7?kwCk?nHT-(Y`ZQ7&*K zJI5(0weMn2=@w>35QieL4wr8liVoRLnrIP#v1uKw{8vl-WMX#C&4;gVEcya}sm|x5 zuA`yTW@AxZ_Y{MF#P1Nls^Y$P`bw5zM?!V)Te`EnKLpb83#+X>b(z4bK`zD)s{wAj zQ4DEkHU3IhaNMe4Lm~|`$|otG4?#d+_M3XhYm22e`(R6)LiGf=fM@0FAKfL3g?y+W^VGwKAch{@>t`Z`c<14&#)=I^y;>|=+{Bp-;&zmTQz9M-zK0;&wScO`^T8nQLd_YG@zgV4b85mQ)MKQ%b|SfWbXUfH*= zyU8D0A@A@?)0XUxTbiS3&gFrd4jcNIyB60(l_;t7SOF8=i2_e&G>_W6Kp(?o2Tr8L z_h52FZ5bD-$gBWIwJmtOHusQtxA_3CAg$!%bzaFYga5pTP-0*0|@Dud58J ziF_G5IQVc!p(ih)q@VUmrdD!&D*Mrwu%@Av-5}Gs@WP4)4hJt@?f4TQjgySS8z6Lt!R-*QlSb zC^>)~Prad-)9d%ZFSOYKYQAL1O zK1khE3MkK#4GmJ|Ea&xz^q2ytzaesp(wp!30m`)$sQI$>bD?LCi#bFcTSniT?M-NK zwL|%)TTw~~iM4~K!)2f16q#Q6Vv#AbVbt;OGmqcNl1v*7$Z-Y!An`U3jO@x{v~<|3 z5v=~fx5?`QeFZe)@5P)`_a_wfh0&rnZlcH|sKUJWT9b*i1k0 zt%;&g0Y-t|op%I})YO~vy0LiQ8?Y?brGdpZupEQ@q0E|bV(hQulIfo_COuP?vrEpC z?(-Tk2ED2+4bM65|HWtb>bCVf(tW1c+_$IWa0T9tt38v!s@oS@s_)*J5{SbO0e~*^ zHQyfY8lS!ZO4JHRISUedDh(ZzyBghMtI5ch#Ok2#fM2e{&uq8D;sfsSSPAliEb4r^?%lYXn(o-@&TEt5rKT zKPvjCc4{3Si1WBA?MH<|O+}`<#zMbJhJj-H2C;{61}av{*5WfA-fmCF!!x-lA}d6g z0Ms}Ce^=AjU=}8GQ=N;z7r<>fjCCd{2AcP#R7J11lvFU5*J#8@En>8sn(;6fC^j90 z9nXFKw6?0(KBRdc+k>HP0P}}s8UT%8W?JfL>$W=NiOGKt-|FOxle90m0Z7D&fre7; zmOidaHNlTNq!t#3ySW(8qo&St@NyKv_hQZ=dNk59;;2iz&arAN5-vCXjz&wkzB4vsy>0PS)Nwo<=0fej>+@M)z_9_US8l$nKoDJ8aVkAkS!x1-mYX>Y_l03= z?OW-SgGW0S3vEfU0f|af)ZO=~zlfOo_E%kKodA`(H@XhmQ6zv=pPA@!iH$8`GIpxE zP7wz0r7M!^{k;3#Lm=AG$ovi7+8CG7EMRx?I zwk%&S%yG<}Q`g&gDYd%PZ@19{UficR#!GV@E0;D;^t>VqiB%uX8$yIViz6uApiSv? zsUtpgL5w;zfY773lQKX4WPvn7s4SSpd-wqQR!SoBx$hq_MnY~)ZL8K#YD4c)i1qfZ zYqESbbr4ZUYO-*fuS^+6KqD=0zY=Auy@re2$mzXJ$y;G$nie%}%D?MEfqG_f>{`Sz zKS$Q19G-CjpDwQ`&_W_{0q=Oo!X)myWva-4Q+L!?r@oy~YXsiSyfv_Cs2g?vs(rO& zjWu{nl2q(fG5c^!nzk)5?Q4*dE3i4KR}CrgP2lq7&9{GiLANNr^biKG2P`jD>x zwi5VSz&U#I{{7$(c-<4_^Dtm@vY1RzkAl&3Ro{5=xQh@CuVRMpv5411fGbR?xzT6~ z+XsxWrnz|k>!$<`(%l8PqI!w>aK)cJ?;Oo|Q^=M~@F*i+cA)00gygbW!24tdW!^$} z@?GRQ>^5%Q_#(*zq^9D_QCORL_tDBU+KcFspXk34XG z9Ki!41LFB+e0Ru5U}aSK&U^y-X@s@v3IA7!adL7FcOZXDvl6S;{QL(=-U!W>rspcO zG*F7?1?KzMz~AJfCNr1P-l_-+dQ!CE+b(}8Ror^30jM>4Z5c@!ZQyD$&o3k))v({p zpQT|wN#S=66;Tem=%slCb<^`15V>*&Os9*fr5Pthc#K$Cpp^6#gY z2L9O38$oo9qc<~VIU4@2pZY7>cp^{e;g!ZmWDL7GpR0j`saco#6N({`zG2hWpZ4Y7 ze^?RG*2Un)WO$xi#W#w91HIO0b;WM-v?6W+?r3etLKmr0zs#arOCOhft!(p`NJqq| zUnYyA@7ziTn~eM6C1kJY((tcF z=lYrrwzc0A1Ea1(=V059$MtY$DTkdwT-@vcC{D$$=YTUUC6<6LZ+MeW-A z_;Zs~P_ts_Ki;#O;m>z}ySzS0e6Aeh?cU=>95WiuV<7w6NaR@h;-*e+dJe|<0WD9# zbH(%jN7h?7MAO{(qv`UZ=*P~X*H1QgrxcNPs!%oOv?{Xa@bQ8f$TIx!=5 z-I45xOZEeL(n)9H)5$1lDZfsfBfpb~{wO5(Kvc|-ed^P%rf(JtR_(OT*44Z`T($Fn0)yITZ8B?QTi2md^+bt2zs0NoB2^#|||Id$i zLdQv4+|MHR0|toOzY#OZi?P0zrI1t@SMyAv#z_|b#@c_W$KfkP9w5Hdmdx_{vhYm& zdtPx-Oe1u*Yiq@;fWH6Sz^lUDF;Y4i)6=o!VXl30tIIF&tiL|$Tkw?z!risEZohtO z;^FdbCnMs^{J)W5%q>=I1L}@^x0Cl1m8w;JC|7MEH-_CK68X0WwpmumnVP56Y zlNXkW801=f+soGRqT$uY&M<@BY+r~#Qq{rjKq6K(aV~p`QY5;5R?)u;26e9GRr(Yd zo4FH)X0W!~`$0Y&x+(58g0` zwM$E1N>|w>WVHjS7>(A(nLk3Te^oSuN3w!rrlKIj{sK7;`){VZG>E+KU#Z5rN!qeY zHm`QXocg5Z0S%WgvT$e<=xpWih^Ll9=Cdr?yLR?uBGz*gW11vbYw#M+F zW%m?|Uues;-viH+Z$MXX&FQKr1tz!;&DZhn=(304bavvUy%gUUt0c<)Bi(S12eK@* zMtSAyZW6RW#=%6x&zSKQZ4enG5VQE{GW<%dg(GrwD)%-U`C3HKml+T*4*3 zq}<#xN8)mkM(z!GFHQ|K%r3c==T#H#B*Bc-6#GxykiWa8i1`J(6X|Uy$uIN18fVdm z2;)wXTPHZAzv7XKEDtINOGTUYXWQsA8-)nlZv9s?A><2wz`JJ)bJvWK9Il-p1+sfZ z^5SBv1RJa1U5p36?2eHHe#D#3wvA{M(%F+y2HelXWSsw!8| zq@hB4r!upE(MRa(5hKRJaQCxN);H?UUgBI1wY-+eI3^^oVGo+Ty4=LoT; z9)wBKB1w}5YyWr8!vqicigBo^_&qa}_eXYLc9W~cb3?gRrpBFFFXR~NMu)ADe_2!p zwhh^HxW}H!o)+r!gi&*r!ruRhgm_BC5SXKp#$_e#Lg8OQQl@$?vD>p!Sx-b3-*+X~ zO-4(R{lU;WGiS3t@ceGDCb5IxkhN`H#OD_x7s7o3N|shgHSk8gu5EUW7DW-g-i8Ls z(5%yyL>>E=kVj-e{?OBPmEfg49*D9mjOt5r`jYGWW4wjKa&r4NJy|mT|3b?Q^!OCn zUf7Wd9Vq^u_8N?N$>A3!*GA~W6G^ZcixK8MnTuVBwB$8(6-wZ%?;s+teyB1qJo-8J z_IomYoFJ=)4P!8}^a^ChKRk5O;Vt=eU~!-SiFo2?D547b5t~4cjW}(}CHFXb<(G7d zUisFu>8`~wr-l%xse`EX;? zE$C7`s2S5gz4p7Qj<%m}_(mIfIP&&*)P#F@EOCtAI5(H;nNi4(wR`Op0iixx`n&8I z5d!`OS9;hFF2%JQd3T0Z^(d{bUy<_#`#@KRQh|j z`zYG*efq~C79lSKfyV@u5?a(6O-a=9{K6c>?NWmhv%6bjEy{rjXt6$dt4EBGvTp&u zGNR8A{JKKJrfpK~3J>qeMIx5b%P{7@`6$@peHqE8>q;?!iQV)28J6fiK>%1S5HzuZ z_wt5AO&WfDmUAEY#Kp2Fw+lmKbpzqo>^|75HsxE?}^Im9P0LnzNtG~ ztC_RYU|mOtymFfb4jY4-p9(QAG;Lc?FFCcPvD<5tAwsbrWAft%Q)yfMj_3t>i9<55 zc>~(-sB0A?H7cdcj$?veXF?S-(KtCv#pvb{;LrS+-TCO{j5%S#eb3B4xR+)^{A*J7 zXHjZNd^w?ejqRGQT+o=VQ+x%V&@Nl&IE@>d4}TfPjk8YA=;D*VWW&rmeO%GQV4 z5UY^P!H=)`?b!d@lg+>F^3j6CRF4V`X6|JlE7}GR8q?bUdiB-x&EW?tgB2wfD(N~J z|N9aF#nqjH^LGr>Z#3@S9yIbFEUDsx68eL+`+_jjn| ziB_W~vLF!ektlKECPXx%!n=vr@qMI`v85)(q{!W%YjhrUw;+aSy)Z7jf~j}&Ht875PWh3r^x{h;GZmvMU zH)3$!WVbwRreM)Y$LhB!nL2l+8r;e%EdfXIt zWSNPJDkuW+mq&xn{d{7-+QC9%Uy}%NRL+^U*--*f!_?(#@p+tdo)Hg?3JzX;hOp@g zG4u0+rCUzx@-B~Yv+qe0W5!>~Ju!K?b)g8(HSD*mAoCSlvKRPbjh{ObCD(m3UFI#;w(elx$x+^$?*NTdgtyEc z_RmQaBe~f-5+7UH%bFD}%ngz;FjzOoX0|XOMh905%!XVl5J20l|HjLNZ4yKtn~ybq zhG&)9Ib6hO0|eemYwW}km*X8r!8bPR;vsDx-UB)eZD8Yf20s~11rz-b6fp>1qjPs9_KZWO(hCu+@F`*QajeTusJ2UUXuzht zSaaANEBU`sBd7d+R_a#5P+;HBRSd;~#N*mDwzsVr?4hX7qt=}L zt^m44(117X!)Cd>_15kH1#4{-Hl~TtgujaVe{Vnm>|V5(nPFt#_60RDJr|6^&wohz z9yBJQujr}13Y6*Y1oz3#$^2?90}n5wuTQfyD#f;Ua&Kqo12@rZjU=YpYrQxWt=8ny z_?xjI&j=^&6powix!v|;N1dh;Ec;p~5AQc^&QN{i?=+Kj4}p((arjr-r=F*Iz%mk# zc$v6+ExlX3t=lW+Z~dz@PAX`94kUD&NWAzm-(#0e<$b^n>?gNO@Um26(~TI{GE zPNg;4s6;k(_Odr>0jyw>=6saMuaG)T0gf_YX)e@y=;=@tPp$obBTGFB$2X)IAu{|j z1*UFh9yWS3Ifb=4E%h_l->0MEqyogF`=j^cG919x;zcLhJwWjzXM0_T+zPn@cL`jWdk#kt3-2Jx_#oe`wykeWFWIhx&*D|$AD zSE=~nK{&n7!TtU#P$*~~c6DQ|^J0@^RxFu9tgG61!`vy#i$GpJW)uOinN!9J%udl~ z-~?UtMdK3x@^anb@lj!Tb$^IwAJ%f*r>g&&fArrrwQc$@v~*Vk`9nk{my1t9$)21J z&-t1Vd#RHK3hZO&LvVt$w9)z_#eB0#aox1!Lh4rY#hoU)NXhNSYvI&W`cK3kUYZaq zGKt)4whW2Nx-H<-b&$=y&ak67p$iYXC_W0X+~#kjP~?I$euB1gSygw+a*yHu?Y$mn z=XE!PTI|?^?`deUr%~VcFJ@5@J?G7R)py!NCP=d>_V3tazU>_p^2us}F@9+7J@X&J z#i@B_w~7JFHm?#6P;bmbIHte#I{BNF$lZ7ui#}RDTr&v!4#1fK8!*b`+w?JCY~+(m zlKq|ZH-A7vajo6*BedVvMa%jA+ij}8m)f}>EU*3;uQcrMdbZs{J+^F&C%h5(4fj8- zPG#&Z#7>6>$^W~yFUre|lYd)`!doduW|~r^mKy5KtEN9cGDnyJH8K!~7?06w|IS`MxYF8O1r_+t%__ zRP1+}Jal)A<;aMO0XT+E)QHmuOEDj65mMdG3d(@Vkx&1GY$W0So%x#R)1 zR*%;Dmp6#3+>e*U$w6smithLQ~`4!7U$skxyR=HsN~x})t-QgeX}jNdG>6UX=aLo^wsqL zy%YBxW6X>wp49VcdObWBL&E}-{2@lXhk_tM)DV!fz0AsPaZqqSwXgG)8Wo91H4 z`o8ZOK_qtK59!SERaWom?9-o+Z_7|B%|?zfTCb%gBGvG=cUmDYnL zXMe&K`_-D%y!WJgid=;Fks}qm9@!M^s-#bPer|kl*J*cpJ$Z-qBYUre=f%)_LYyW^ zU(CLI&p5uV!n)-Z^;!J;!z7tz7(x5i-oqD33=lvw>uFFW(t5AS@J>TsNhu2k zj+!1fdQRedzZQHxe{}5!*V%SXRVG&+JK>FeS0pd1gp2(0A$j9k$I|6V(zfphsVIs& z;oBcSi_?>|@3qt}%$vPUuax+@erJU77HK%SOL4q^8MEh9!Vn|B>mV@&?uX{hBxy1O zkZ1lkOs}SKD|O2Y@VmWXKKb;~(pZCzW*4{(4Ny=`Pdw`*@lG)ZVBUb3Xg&QI%RHR6 zSVR5gi(-Iw82xS7J4GL6Esjif8u+Vhd8Y07pErt0m23kirz9Hm*1g%&jt;Y{eoNsP zhz)U#D;LnQ9@^6?PEmgUxB!EY!@_>bh;yu{kxuFx3M9W2gBdP;d*z7MH?Lt}x4X4D z{=4>xlXKr?)ru4~-8X6o)4;L1n95zK?fSQ7t-o$e-V{3U~iIE0D6C4e@X0IXHa-5@|we>$YQ)&j`ud znnM1=z1lIZf|5o0F<5o5luME2g25H|vesbD>Z%472c$*GLkUm9iMK&5cq2}!I}v}u z?mKQ17#U7V$82B8pS-W4<_xZcQ2vPZn28z$CKr`zL}l+U70uaL+`1_o*ckglg8Eb8 z@4C@_QH5Si|2`_uyaVp-7=JiEuG7)S`?mL$$-@Fc!oBApRxVJRsGRC7e1^~wUvxCk zeH?!@cS{y{ihjXPOR<>jLl<#y6#9A~TQidt)j_AtPDXJqQ1%-|-zqxcaHm@`P#c>Z z^eb4rZ1;)ykZW@~+mjkl8p?9uFvs0xj+mBA3G}4@mgiUBRK9UzcLRHIQ)`=VDFS)* z1!X(w`!FhILe(DHj^{0j$JPK+Z(!w-TcZH$rQw(+TP&_MnCPEH@4%u$rm!P1(L3wD zYd`BJiUi_?5_liW=Y=lhrs;ipOR^+|MEdkFlAeS^tV(e;Kypi!heKxbLm|;MOjbiu z&C8~AI+f{sa4Jewf=D)8nZBjQ3!$@CzPM*EwqOyl&L|D4_WkU9V78~2pZbv$N`_9H z@;X0?&mCI}iv9aP-My=rWjDVcW|Pyx>i)DJsP`G$Tdhg=D|rvfkk7M;kJunl$ziIo zLiteW(T4GBth#>hX)}{$nenfw5UwwrEh%x7ocD&f;Wpp|iGMSbliF4?exx^HfuO)3 zpK6zk6{!+YMY_g)2G(Tq`=aVVO>OS{a(Cl4 zw|dp95EUGkh5aZ+(#`OlJ&-U!7Q@#xe0BwYB*<@;>HU4Kd9VWNqRyNZop6I-ZR;UL zl*Z@QyhyV>L3&q;e|Z8Q$dv`g`;!HXhu-A8` zzl+MZ^gD@}G4-wJo2)WH>o@S|v^BZ4KDg@rVJm4IKmRI1>c5b*uq;r+xIg`(Hc8{A z7**um{W~B-PqA0@XzAu@&DC>A#eM)vv|1w9ho+k`z0pgbv_CKp&mQwY_y$H>9ex(y ztY>@Y*OR?1$=P#*^GgCTFDR_ll2m%GQc5P!H1yv@!c53ie)o4<{K1JbA>BI+ngm0F zCq7#!x8AmT8nD*aG9y)mCX8dUn3a@c_68w9Z^X^s>AyoLpFDb`qmA!{HMR1zO3gFw z$ZAw*G+{ED+2RTSKrwK9-kU}TX%~*O-fdo8fl&-N;k8o)t|EAHP;VL$FFvqfa@i26 zVM3j^WDO$aOY#BQ8;heXR-KoOw~%&Z!yK*CM4#}^)yM!IYMhF-Z*ut`=W~)T)D=^@9rzm{gTB{9ZGRr@ zhs}enZJS?%wk?~RCoUmeTp!G!7oXh38>*LZw|D`0U>GNOO z_hl@$_(7d9`6Ic>;o+<_W2*kdU%=8?pM4__u>TvBW0fd#^JEF|-jUmI_`{j$_pp7D z$B~l|LPf99Dx}OdM2BlbpuVT=<&fQ)|Dwp9J&$Ut#p}luittdxR`(xE)%mS6=F#%RXH6$zm>mIJ;;%|KgUVaW>YY(SS5s*h`7S!-8>fH3%IWiZd;V?K{}3Ri zGXj#Zw#KrN~de7q|H8SuKu=2ZJ!tY{u5|sR`ySY}F>&N8iu4rme6LHfR z)Pwr@gDw+C^TlpZyL;Iuf_F=GZf|))QWb>E9%QRZ%}%J_gkQ;ukk^fzs@DIXO8cEZ zk6^^R#7NLGXr=AZlT>r7P?u$mltY!7~u zkGKaC2H*R=3&Q6Z9MKq-+Lett9){lPn$m58cCY6PsyRf0^x$yHPo-D$%Z=Y};;=sK z{PP61`)1Cp#fwE6b1?YESO@SHK1-s@RO)UYsKy98zVx{GGZKs|Y1#AS{V=J$+ymyD z+vT>EJ>s4h8mD0Y!FinrAG5?onb&b=p*}`+G+(Rb>D%#x`LudJ2mQ?Zt_1wg8jjt5 zwiH6XCFT*d?J8(!m_!2fc$Inai6;{DdjFPGl$qMk#Q4QpMe#>T`~SS5$Jj6dnU!r*CRL)U zH0(^u56*w=(t)fYrDrREa4K0^U)5QTYR)`O6cC`^D2QDk7<6#6dfNO8aDiKdB5B z401jI;ttlNV_Z&oMcpt-vz&kc<;VU%nKooR|I=M@UCu&(a<>4AW45?4Z@0<3fAr5p z>C)!iEPVc3A1$m)X}-NFP1$nbrnQ?yChF@M8_@i!bNt~LmGF*6?uhPNvcTRS;br21 z+omkCQtrN59D;va#;QC{xo#P(-4338#7Y^_h1%;&@wc6wF*WgiI_%PZt<033i5P`@ zcMi%Ok;(;B9kSW9Qs9`Pm-MIoV-h>uO&a@g16$tfPQ>i26q^!XvFGYU9z8qA5KjU-G%gpp| z05RskK;>+1CPV6YXJq9V$YYDWY80W@WBT9wRVUM>%Ie{)L)|3N)!oyeqf$WX3}`MH z=uD*LeHtwIn;P@NbU$_L^7gVV-vJ^7kpqz1>`1^rrlq96V`^jCjY@W`P1{ei=aR1< z`Pljg(VK!3AeR1E?QJAJbn@_%Rm9ny7YIb30X-FeH(o%+CvJl$;H97e5)^f&uIv-BN z_u+pCnMw-~$4tg|n1Bs%yciwA8JmYT4x)dKE;U0OwGmiyXuaHu!3!eSEX(k{G>L5!-pd*#z<5TZCE^p9umxb zp`3L*?KxoYqxvwd)~9&feBY~D=&uO0-+mU|+$Yg+VR|yD3h6*hs+8F)qt>V}sb(92 ztKDrh1O=*c$p-D04Rr{-ma`ZCY_5`UdNuCbT)DeD5B6$YzW?GPhu z9o-b9>Z@h1IDRg@mlrUf$-M8)$Md0DKBYqWYI&(*yXx;_l2c*8?Vk-iFqCv+O(x!< zE{`yoj?0d$nf00FvFYjQtH_nDOxXBL;Yb(T8;w)9#2MGxShOC~zCV1Sd03>sIIFnW z*Ve5>7yMu=K?fVkGE$#=rJv0Zbce_~{K3rXF9ND5B!vR$Hv z-N77Vf8W1^$)$|gSw6DcKkYY6-nwA!u&mJ4vrFq}x30=9D9Sm?b<@0>};;&K(4?D{R@XsdGqv!VBZG+DjB0?P{Y2^ZaL(!eb`Yt%r8;?fo;+LCp zp;F4cLrCRFfA^SbTKvUEkKH2|L!@!10a*#AtGV_t&HKnt*&2&|U-;zjVQAQQ3IJ$% z8D7mLkRhBv+}H7_`nhQX4{9c%F`>R=aY^k_DZjW))HIXQrh`EL)ri`|l;0SY)J3<$ z=B+wi%C2^kmE!t`GLT55sqU`GZD-!W}D#X|M$npOE4J!1H3= zxn|FGb%9#p1Pc3(4kDIkQNzW|6a2hpM9RCqyR;foiSlFeRZBJp+U+(M&NN~3zB8T zKjo(`)?r;HK;*RYlLki*(&4XN&uX&Bi4Oq$a|L6gy4*R+NcXdn0I6Plgv^IjATn#S zwUz1Ar4+&w{9UW)AVy-dJlxw>P?U1vbXMOtp~HXHm+}I_=X0hBsaq56h*7($RXplC zjs1;$5YD^reuwH1ce;usyerF{qMpQ6cI&jWC@3o-nika&9Dk$3obeEKlx7m;zJ`oA zG_lIGqS^6(dum>fctvZDMm^0C4+a3BHovJ_+dC>#>U_3t@$zMUB1wzxmfJ0P>NdrW zU4IJu7nyy}5#wA-2KZJ}(~M2}aQzHluX6?XFE;JVnx+_NyG8N%Gw0rKH$ok-cTlH= zYsM<5hfOcg4f+KB6g*kc24cgmT{7DxoDG;pZ<+TliX}hv!A;a4q+46suZOx#Ipm4JmbQVJ0W z&qcKpok^qV^9GQ8bX$DP=I6;lkA0|F*OE?}hdg5u7i1^;LTTIhr*l5a5Fg^KdUWDg zg}!}XIVYznf<@zruJM!j;Rrt;?o7kM#Y?UoGh22}J@hi=)f|)*=RZqmRE8%dDMiFc z#_~#>sh8u5HSrCkR#AGlc32wg>pko7I;9OP9{_FkqAmK4Z19rDciHB`xfs4XC@(r` zc;#3fgnOZD&=oU3<3cfBI!8)RQwR5}sXfy^d~FhU{R~@zxZ_$PA~t4yjQ^An#~@mz zvR?jp;7v*$SZ-T2gZCpzVhFlEWFBKdHJ!{JHxsXy10KeCd$y`>)sc};K*1E&7RzqJ zadqg|egASsuD6nY1j;;^bbaG9Kc0q7PIBgUUU(kfmsbIWTJ7}{`ygF#0U*)4T*$=2 z^gI1#{o`*;VdyngNgZl3y{?mr2-fJiY0A85yV#1#rqBHbPhD(}(JEP!qE@itkI+mS z%E%NejdntfP8f2ADI=t-$% zzIkqLUu^D`WVXIuF`&c|zs(xOQ>8CHF(}^t{UKcyD1**S`;% z&%)!^bTF;6`z%1=KrC&hp;fX;^6kFjM72!uuhuNqaLSofh`N1ZRVyN#216Hqc5sM^@4)Ggbd~MpywalVcw@|uoweI* zn=IrbSydO3dMD_!(U_4TWrYYWwCPsA|DeqlRXtIEX$oJ{z};U1Mv}=YU)M4d75Jer zyv&SPuc%aLIMG)50fW32^~NIe)!(ttMp&a~SQIvG7<=l6oaS*dmxi$>;$E9s^K7H~ zcq=Z$<}dxJXR=?f+VnRz(JPDPdT;y-YYWCo3V+wgd+gdBz7APkU89BpKdXRnT&Zme zgqhUt`Q)*w760>4-74&)e$1OsGebYu+84v@1TyH-{mu`kwyGm$?LN#=lzvM$#L;NC z3JXxIqzj0p#Xc`JR?asoA$U#&+A)6tjnc93cI?urAKTR&9cD8c(PiQ5%s*BTXst}q zX5m7zqzVbf>t0^iw49K?LkGh%3vC%+%lrsDZwelkQR}|oq&}KCx#vo=Tr$R$xyS#^ z^EShs(({9;o(;b=bb7~tvucBJd6pSq=* z6wqG^MoFX;tfZ=m!3)!iyBCcD*rq#6qMk^EDM+weD_a{1xxVivT%7xV)dh+-TLS!6q&WOJ3}c=JrP{;C#%XFj zSWH*tUK^FQHPWkNVC4pP#~~0IVpEsmd-cikM;O)s{)^R>eEYL&VW(HvpL6}jtlJHV z-5)Q>e#)(6DZAbD=d}=^@rFzaQbglqE8(P{@*_EW-PK?lJ#^ooGOc4fw9n7(1@UmmAaM^2iX~S^5J) zfCI?4#VfPC0Z|`Rk9f>2Peq*?_rlP6o;28h;gzI^;N|Ui5%D_4jpkhnLxR5@fJFDJ z6I6`*Mq9#HOE+5agPA_2bz0>dec5mYt!+y8g&00+0)JN+fw01z5rzgbpk4`FSEX2k z#?$oBw0mTSIocQB;ZHE&X+l--_xdG1p`jbV>jASXZs6pjz+l1IfbWS*U&ZYZM#rY4 zt2;mCsB!ekA;uQ zL#&4w-Z56-zU6U%dN3&+a8g&g62mDQCYW$yU!p8;NjHROR*i~zIsG|)J5=MhRTA2a zHuihfaDV?Nj0RSnHen02IJ_YC=c44kbP2;alw&aQt26+8wT*|lJ`9(+8GECTdpo65 zFMpjSUHP74)VVnF1^y&K`3?3{kID#giK`_2`>Mmd0E{8yeqsDrNuUFJCXFgJ8B~J> zd0IHpejXd4pjjm`>E~;Xk*aBaN{U-CVNp?fcNOpGAZ-N~a7~s0p2z-CD4YU4948^s z1VdjT!2f)RVg0yK&GOULwe@n|jV{oR&{~>{>yz`k?JDOjQ8$on_`J0wYO;8kGk*A@ z+bsf|Xg|#{MoYKj5=++9VgpQS3@}R@ zc0Zb5qvS%S!;4f?l9qM+^Ic^3av_*db2;@Wm)lf0i42=7~=!^ySmkU zuQ&JS%B^+{Q`CPFb%fl`dJdIq9|;e>8uP5eBMCbPitqCPpC zw|XD;K8m3)@|~fU^FBTt;u%-4zk`BP12{d3YvYYg}?_Jb) zOrzG4bpR8Qqk8U)$(#J^C!8Xs&5!H!jANJS3HIwgN3-xvW0vEVVjme_&Y|u@pU(Hp zhP$(vxdD5YGaD`}g_UkH9Pin=n&vWFT~{#Q9h^;9WDd7s$A_4kwkN-8!^V~U&d$g? zE8Bu! z@}jOeU;j=DY_g#>H8Wmg_soFI{N&e@@I^&FIe%?;7M$Hw@b!GMVK2t4z7?KA@_spK zOwcscXZ6=`K0;!7^Z^9I5Kn`Da(@blY*d;lhE&{qOM+D`Z*VlWDbk+>EWZrArUKWS zu7PtWI8!Sv&mu>8GE>z{&LG7hne>C!mQoyb<|VDQO_qT#?O$G|RZ*bUJo}p4aCU>i zm6P?@dC+@s;f?0UW~WkF299aOEu09r-y8GBL`Dj^4~PmON4k1|8jzPA`h>CIXC1RK zuE){S*e0bvOrLjw|VW2en; z{RFVA+70@@=8bl*c4-Cp0RNrqZ+0|qG$I~Tx9rEgirv_GX~;;Q&Is5G=E+6(6lolU9Vq~Rj;fby6zpDq6BkN|;nc?wG(Ou`+Z>W=^ zL~;Y~s^_#-G!k#0*pc`vf$wXiU|w-6H({i;dA1J5N(xN)IhS})z>2l&s@fK(Ww;D6 zdwO~ewR&g+9VZ-m?@&(*R`b{V*taJK~51b9S6_I)YHxzsNDOQ zi>i7vEV4OuyhOp+5hdR8B4 z(TQX|uGwAJ6rqyL0Y6DRU-mS~L-gb=1?Kl_I{lW&Lx&;d!h66p$Rf}O6du}coGV1X zi2#b-FKiWtS&(1Vw7_p|U%mJw{$sSO@J*LHyRRBTL40ST%Rfs=vJ27yW@BEw3qPNl zDeiF~WaK>>O^C&o;M=#{w)`-lDu}5Uoyh~Y!>XdEABwI@8N-37|5hA)75)Oc~zHfOHGmnyPAdHZ7+cT~6 ztp(DZ8a40an-TSRstC~iH3Gu|GW8>j-&Tu(@B)%I(+X&@Dg*(fGP$2nvePbgc_6Fa zjFY3;d~3XAdS6pl9pZFu(BgLl9J{eHvY~*w;uQDX9=b*dBgqN#&wI9dsHPb16P|bO z{k>w@=EKZi8rMnsY(+WJ`1w)Gch(UMKiQ}e*XpGiEFk$if4#bHCA#}A8rISJRJII| zpK~P~?<@jb6?5WNPq(|929mR^NL~u=QF)eY8zvWgd9r^x&QP^zdtaYuR9;4ul+@0+ zAylB|TY^~&7#{0F0288rj%1w^r*h;LF)0V0r{`{}7m2ItHkmGHz$)wm7R$K@#Il$u z%IsskCCc416L0UGCrBD|f?Spifj@bC* zN3j5B%CLpL!b3Ng6(5fD`s4DLfR^ElxPTV%@Tr>%AkNB^dr|n927oDFuTtV;@CP){ za@)jtI*ixO&BpBR#Xlh}=-gIG6Cprk{W$5)4Q{&d_$h8GklCzn;66Y~ z@2{bgmfCY|l08(nL`=|fZ<`D?#lmri+?sVXfG1v8+dJd1y2<|cHQbaN`}J>2v#t?Q zRe=vZ2oyx0xRr5!Zug=p{igLKYyy-xkctMME-+>rb+kGEV(PVDJz}ACEb13l;TCXu zZ@T}X1O_e)I=v^_g$yPs9e++$NiMbF%Be;(D{u&_Ta*DAclTTm0NUSr_7Kzj%9k8y zm(p)E8i|uphNM8Ga4_JHQ}|^|?yY3P(LhI?+m~=$Twux6cOcDf(a#00%!w=eO!w8U1B54zkY|3t2wD2%79jl3O(<@r`&gFenn`Ul ztK$Rod;)wK@6hfSe@D{m3IU3kVrJ3LdU*CYof=13G3~y*3$wgXYvfnPLDgRT->EbI zphgruXT!+6p{K~D7x?c5&@XR=W3Y1}bdFJ03!};cg#H_#@8idhooyCu{*vamtXmCG z$OUlHa^eD!x$-O8HzMWpKaV4yzJhxjgL~*SIBG^&ib!!oA#?rDJaX1PG$gYdDU{lW zRxcTm;=~rQe4ZqUy=R-3OL$1)dVpy@N`8_1FDGvb>j;=%=4sDigj zs}7JbjN)0%h?;&zpMc_w{mpkyCnkraf#q|!9Z4%fecS;54){B+N*z)r0MIE_+0cDA zsa~#V9`%~~297CpC_&e5_$+FNcF30m2)GXYfk6%4?pYo)kaBH0&zff7oW2Bc$ZJ2h zdir#Y*e4yp*n#2T5vf-MK^(uo_j#n}zJ?Y>5h;LAAaCDQG%FVvwymjN2 zbNaDpqKGSb1h~^C+pf}VFP<@g)9~W10Db1RwMf~ad!=}GxwdPe=Os5#KAG1 zC3U=Bt}p^JuP>^~g-Y*YzFWnQTIb3(=nSNLNL)5mMwm7m|MRTDTiR}aaM3A$9zAxn z1dY1{0sW&(B*yFK$w)e_oIePlKdWBlV!d@z>QT!1)wS-2j;Uyxz1T;)mSY~<43lAI zQXJ3NaTvpNMfD%@oKyxh&wTvbx9Ad+hE6SEBso)Tm|&<{ebq(-gX*2?Q4=ltPK9~# zVNR~e!&9FI%krhW(|6@yMFxRJdgkr07#l0H`hZU>&B)83Ge*L@*n5EVVBj& zOeq8I-3nFM!^P>H_FKWTPm9;z@d6{tY$kN@%x2B}?6ov6UY|7>vW|Ok-`z+Wd}m+3 zk{l_9*C>B6_Bg4Fb<7#zj1Qk+fB|OrrD~uptDFO=_C{|G+DW&JbVMDab;ajOjpE8; zx1*LWRQ6OO+>On~E(iH&lxjs7>!VQ^F%Q0rT`|OLts_<;+t})c%vrqX6Uxf78 z_440s7B*>d=O@>Xk6*w3UzJNm$T92^$8JKRLTtTcwS0Z{mA125hePP>3FbLz&f1Go2r5Gb)VVxM0*sxvI%O89R27X|FjV%i_jc$%Gd zu)-ntjb7;L89!(W@eQ{HBFTgO*}~_5ooSq^2*0ZdKb5NKT{1W>;IA>LcA0{(Y8;6f zxBHMN>9o`*G6Dv4j;Bj8GVQA26Lc_~@#x0)6I;7?OB!pNJ#xA~Df_!daN<`|Ce6X$ z3Q<ZV$QXh*A-45Qvy%50~E z3G1!i1fJgl&;Ik>hNdtWPfDQo+Q0xCF!|X|dSxKfp#KmxGtnU9RlbS6CUeukfJs7n z`WsvO5H05_ei0Mw%a!3=Wo!txKyb2qf>UbCgKMZt7 zK+C(Zh1$9x_Zmbh{!ZluwyP>jZr~4}u}XXlFHKA_`XFH{KuV0(K73c}z3I1FZE9T4 zsi?B2nOZ{}5wDj(1#aQnb&t(*-jdPpPPkrFxalqQz3!PKpUc!AZb~=P;f^*Eoff;C zw_iJLt{>Ged<@7ZgPWMEb!JaqN6~_|?w?H@b>Ho%mm|a2-*>&S+#iPTLrt(bQA)>s zS|ee6wAS23D_vtjDW+e^SYUw8TjC8W*68I<96SejhGM*TrwzJ{F#EG+*5xRzKjjRb zTPCAMW)y*Xx5;OcxQ4i_Sq>k9p@sKJgDa%eG`GDZc^0)!i@6OXl7SZBWB`jExJFNB zU4H1U)g;i7`#|@ZlnxEd8Vuo-l6qJ>8W>I{kJ@fZA4D8&-hml6U;24m#iV=NC_fv7 zx}TmkV?lAzk@Wd}*mMU6If=uXWrd`2471mxIqaV+x%Sg?bCdc^iovbuK<)O;4aGD; zpUlB`XNwElK0~~oO4D8MFS!&`8-1%iRvRPYuj-IPJlo+o|7@f{!-Obs}V5 zZZ#o-ur>2%+MWkzpRUP|71#PyqfaO0Lf6^3Xzx z?oK5f8BRZIPCN=)7z+PzPCmB4HGtogjpad@k=*$9rl6JtvR;x@OL z6hsWo5zk!Q+7;P~y<8>b^ei)H$g$v4=+v~{FCX6(w0d0G3=MZ%!gzw{J?AWOl_Cq2 zrIx5)_4_xz^$2Lovo|@M4E8>}5`k9akN%`flP%3({DjF-OS=9LhXC~oY$os`a?>~9 zWjrtJBf%JDJ*Hx9ilLR(-mK97@=STE-GvuSL<)ZVBKYY++-&T2e`CT9R1ddf)_>Ne z?G8T^LFo8)B}M@0dIK-)JkhXXWP^*a`%NE*Wv|0)IAxufTlG3!^J9%W+#Okt-sZB{WewW&1u&d%+&bK%T_Klv9%X?;>?+G~ zSbwvuPplJ2NOEd772eRn+7|NHmb ztfXvCONGkF`X~)Vg%lB49qXheGpQr<9H~CGC{Z#Z37I*Whf|S~EhDqYUddkP+}G>$ z{r&Fyzk59H_n*gmyvFsq#`Ah!7f{B#+J8yJO8((6rzb@fu1Tcf`Jo~b3Wco(3cSwnr94$8$T!-Ndas?8j zg*seooF&>Ff`ff{VnT&agk(voR{9(&zh*E$6I{PityJG7cdVt2-gSvumSm>5O*B?K_*{ShY+Sv zCdf*TFwQ>MRP;z!tEt=s`&?Yd8XjO+~$)KcfGD}$UoS3 z`wT9;Omh9VCr^w<7N_%n`&R{0;xEjjJ+Y4hC}4%d;NF2dpOb1LnB zTN;66_O&Or^;B>z_zo$o4u1=8vY2tXk`Npa$EtELc{l%3<6TKS-+-@Kfn8gY@ITdGqcis2_F3F`& zUk6*y8)5-oZ_lqJN^(`y@i-;op7@$Mozkp#_iU^8+J2fIReh$j|55=BOsmI$mk0-0 zr_5#F^__fL_nzZ4sc}mJu3_^USU+Tpa7Pr^C3fnQGx?nEVmO|N%gm_y0kxwn+WJos zLC++^N9c9FpY1uZHQZ17OMYPOGVf>`d3FDuT0)9u$?sovE7 z&38dDyB{zVRpL%k`-ZgnnooC9^P9WA8}<0Q2RCC1#b`qWWLDk2(DnJ0*s4>0QbMpF zqQ=r{wVdr+bNRjO-YsoSu3CMWVN-4r@-$yqr&0KI!c*Rp)SXYc{;FqliKpVbcbvQ{ zKD}M0ShvNfxX@E^tu0}-&GF_tAw%}|v?m9eC3{K|YU%rtF)vs*qn)=3264}hvO9%~ zA!RFLQ$2HKrz(aHx;r^n1uGaP1~~kS;`g|#LizMhz9#@|@|I%9#P>ulMSQE@1K1C@ z04Krw7k>t|BFE9a?Su0sWzqbY5#EoFE;*l=tqw0&BHC5dPcIfSY8(0OR1ylFvW(x; zIVPVef7>!t^vke7@V+3;*S!67k2wE&6P13^7Y7G|>r#OoFP)1nEMs!tJE z-Sns`VSib?^|5Z%n+knOVHe*U3U+wg+zOVIrgX;fhPxCTY|!6)f|GCuE#%CqcvapP zx-$zcrhPJu%$V5PRxkumP?xM6n{<=QvN-l=4>6KF`C#ztUgyYRv5#O*=iL1CSEALkH%aEtA=ljwBcX?$ns0RB^h!^sd)0pb#jWbChp_aL0YcIH5{)xIZV zyfO^8dZ#d*is&9+uc}~{+z-@T)6qhuU0i$sTn9RA5cHI~>ln7U{nJfrnsTQ}r4OHq zB|+s~=d(SL>3XR;&*ih_QxnP<&9ilVDkJ@r@Ywn;{*1X5r_S>(--2y5QsY>rEw`U{ zn5FkxbWcvSc5QT%#U7kO!eSBHZp%oj%s0<+9uQ!@}ymeKX57P54Bz@&}$d` z=W|i7{C1Ou;`%;%NL62v_0%KNZOOF@4kZDsA5UC=;jtI<2PR#}OUl^5>}*@uWdVl8 zCD4%RCPJ*(CqoItY}J_>D}Or+YFj6Y>vKx>ajv^)hYRk($y=f@O%4r$0YE@$p zQ$ak(ZJ;ibdg#=fq)C(2u$>9ZuJcD@#j}ohInB@4v9yOx2p8DSW0-#`tVq6{z--ke z(wQpjcwKpVcc<3s==}xw7q&LeqAUs?=>s>5Z;m9-HZANt9p1~hKkII@m?74;a>wzC zYwqE}KP%UoHum}~&dR_u`S+#%dGH9Fp|m}sN2AnopQJJ`0KOL) z7Z>40D$#Os&GneS69h#+?3MciYBSSp<11I=)hd4vyLL^}hJ#uqi+G@@+Ole`6!f&eS_Nfq*Y#A3zqMdT+eRlaw$RR_GVO+9`J&)&X0*CA2) z)oEQ7R-zfV+hhSwDP+s0k480q?Up(vOYUbsI<9}<0>P>Bk!Qi?N4m$-*911M&Dpzf zIJW&+zBwO1DomZc$-+$2CA9CJLMuN8Qg z28KotQlg9r_UnS{5Cbd7ifwIn%0?>trAztJgi2&4ReM~5JQ1*R*mPlNGDCm*Cxr*) z#UBC~j*G!l;GYN!z`k-Jqn|M_SMm#yrb%$Ov z^WDqALGyj0u?cM*P8ebxPB9`Ie8loYxm87-pPe{+v-I-P5dRYR+Mm_hWRrN$$%YR- zC-a_kNS@FuQ9hn4t=7?|*@%%XS{=rG794;WOVQ5s;AoFG|49PiAZ)>AoIOB{{2jwS zLLfq;%{KAdIaDZIjL}vUPmFHWSSh0qjJw74wW)hteY26}MbxkGsNpti-y*wH0)`g< zeB(+p!g~zifG@^)sG)9jQ(U59;QeF77*6*(Pah>C32@=!39G#`9hM{u)7< zJP;w%;3wwq0pgQGOP`c~lShR$oye|0eIjqAhxC}Ek-8XhljWTS&H18CzP2<+?pL)Z z1+kmuZ-L?bx?=~Xzz=Q&V()e2Rmk}rlBYg>(iRICLf7y z{1p&6QO2X#_lE`qsiYM}z?zl0STJtQOuPZpD*@sJ3VPB_M{8whw=zsJuFp?g8W}EU zSa{M^dL;pp2TS*)wrZTQlVsstertNQE}yN~BNUPW&Ewb9qfrLqc~<$d{WG=sF-IU* zb!|0vyoP-g2&Dh%`rf%P(Q59!8aNmMc$eDWLzrSMvEX)^VOdje)h4|Do!zGX%r^kb z40Ua7@*0bYYm$s^hTKE9eti5=#lGMw6^g9ANK|NOpCzu)o}x4Bq7P(|Aa+V+<=|;} z=@Rp$?Ls%M_-3Zs(rO$;g8Kcs+uGX;lh^aQPL|21w1f{KVNz6IISw>qjTZY{|0^>- zol<@AJzdLO7`7KtU)hAdthI0XouTY>7iIGd_Xk`ecLV%7u9uGo$x!(WwK*_@b6WUHTYq z#~g)nYx@1alV@UtCrqswR}dVW#Cs$AWblhv2l>hJu`*tUYEc?0?tFd`LFY6FiBNx44F%6@W$91dD(bo|L-)_vgf2eD44T zekd$bXM5HDdyvZsvYyU-^3U{I%D?3oxFbV{w(uC12G%=|`E=?!K0nr73X8xLVr=rE z?i1}d^hx)TMZYx!R^IWMYEDzOWxF8$ey1DnO_iN^zWaW_2IGFTW252v09O6Ux8uTB z0Ur80gvGb^l!@w5o#$p|X3b!;568~-ZZ%M!)kuHhQp>t!&p=VpcyDyDZOj{6nt4F? zj-vXU^ZCSL>`_0U_P2iZMa+JyIbYe9GM6%_1ay1mtYl41Mg0AgPB#Y(f3&_}bru~` z$3NvlhWiU$=c+$XaIRO}rMyruAV%agR=2i`|008>9f*A;gBo;Nh@gT`8(6ZLYU(H=ZOh==sVk7iU5&Y}aW}RG*!GqBB^<^}DOL zSt>t#%g)A6Qe20M>RsI`)=HoOc4dPdp|nz;Y}uzSV#wVfy`Fp>k(OyzV#o1T=5{Lb zyOQiO^2&}K`|@q`3{Ua>sQwapt|OIoA#x>WlW;e{Ty+TNC7o+9m$^;dtRUKfoX*C* zuZ<3^aF9n3vZP@VVQd9J0eU9)-D6()>Vnw$qTx7wyf)Z_`Kj1dRO?t3_-`@}7War${vaV8A zOpgh{c^cVV*fM6l6tTT^tDUN5UYVivZO0h_Ex(RFTZ50jRhf1ivx7gz-#bFS;JLYK zBYH5rQI7rFwt})ZrbYvQLSq@n&&m4&TIIumk$o*usgLob-~$dG8$p(%wXf~8wx5qz zk!j>PKbrP5H4jcZ-w+Eee@pEN4Ir2@qJbGE=i6`QUNKM=meSH|DHp~9ucWGxv_cc zEBJuEuSb-SG`zhv3-+q&vk+@~aEc>yi*u9^EB>2(WlsP1dSAI%G7#-7=1Mc5+AYZVzXbH-jRUI6>90QMRDs3lC!b&c`XHi8*Y8~^;Xt_XaOlp!*)Hj&fTY^S zpC84oxFzdruh@7&(vk%Pd(KS|1RFHD`N&Qu(oHS$9o2Xj;ffZZ#XKfFIC7mm3$T6FE)eDFlu>BCZBD)-~O27Q< zLX4EJGN@baG~RPrsTuP1$RH$@jWW{MFon3~(@6-luw9_N{z7ea&Lxg#+CIGDy|WU| zSt2#!8DGx)$`Xjwd2f)Q+P5qi!BbN=F@_`O;PD6 zt@oFO*}Ae3GNS&(sYJJ?JEY+c#fXxB;?hoNycuU=Joy6l#$dN$&1Z*G_B6BxyeLh6 zISWun_FD^0mP9CH0M1cJR?OKOz_C~cO4?b{QaL>@#)9`_@Fn7VAg1F*SQG@sP1Xn8 z^Hpc_zjR0=ACxZn`eWUP?!k7c=WQ$;tS>G^)yI7;t8;b*d6R0fN3VPZO4V~bvubiH zq4Y@7uAKa`%Q1==+d&Y8CrczxmDt7Jt-u>}p@%cHXZAy2{y#{~nDz)h*v5oY}`XY>3k@VAoA zowJg>zJVR1X+oZLj%{5~%QB>73TJ;G3RXU5xZN(guzt_ylFHXmJ6N9GdtsfHVscUx zr$VvqZ3YlJ@=h~|d@Ae4xiG>x?RUJqr|B_Uc-ih{m#tpJcP&^OZZ~K2M-4*uL18ex z#n{4fKYwS@J$KC-7GMgT1wP5(X_E5F_xdaKBZ6AGaeUv#dimMHGd6CleT!+E)v$a< z>^CUbf}JH?3w7L0cpJmkV4i)Q4UIQYOhe+G+lHx3sP8MfB;+l~xomYB8lAn%|5p0J zF7TIc>Rla8L9H`Y;o+7J;^a(l1Ch(Z_tBq)!21c+ieQiSMt<++?}dt<9}C4Ygt>;F z5e7*J^XPNwUM)^0yCUdATdKp~egk_*8BjowaQ1;VZ1S9&B(<^8s7Byjkga%?Sd{mb zcm>96%b}E$JcyH76&`Z7${P7%TW@Ec(2`hdGl(mu`X6V(aQpTN>t9Ab4;PE#WgJF) zhCCDQ3lcNpz*KK{59)f@rSrUs*1e?Wl{aLU%BJ9*VlRcVt%?L3#(5m+#s`^3BN?&{ zgLbJ=!#2p!^pqSz^sDNjI-&3jXL%I7JGTgz8gH#VB8P>jqjXI>$J*?C?{+Mt%x-FC zezlWHID4nDjS>o(bHX)buW1ik%uJi03=pVwkU!!99C!eKL~XwH()X8))3hG<)>{n~3gJe>Cs2_H|^c z>^Io6W*)VNR~f%e)7$K8lUaxcZys2y-FmGP@O(`y_-lsks=-{+kj9mu> z2X*?`CnJdkFDH^v30wXKh^DurA!!S;paPxP#rjG>O3IS&^U|Etv)78WG&BBP9;_m~ z=~`uci58__RUYY;0|WWo77IzU^Adc^i{Y%$FhVF9W=*KxCwA6Fr169f1Smw)fz>7E zmId!8ct3U+xCK;npd~7(9h@;nN+)QlKi9r{oQG_Pf>OcU|Se^ddif z(vHxhF8(+<;%`72B;K6^B8YV4TLo@c9%udE3tK4z1A{_jL*yHyQjv--OoS zxOizo+Y|hA<_!9dQ%W04p&fm&7_($j;7w-C+W3$W6l^t?ad4&p+)ZU1)e_7iH&RTk zbbEbg(8)@LN*h->tV9~i*7tAWN>GdtMw>)&tL--j3Ig-K>|J%sof@-oj^BWEs_kcc zxuOmrCqI;4R#rM38oOYY|FXK91eB*dNmd2!+<$x=>X#9NMWuKN*nrhcqhEr;_CTZW z?ZemYZq#s^m)*+s5T-45s`4bZN#fbxlTisgl>s$$)lt{t4IkV7sHWUR-bCuv_~J_@ zUT;jpe-=N=TZWtT_ycYtMT%iLqdd#Yk&fPjsNpX3cU zAf&zmu3pkjy7!DDr|jTi$IXP_Vo%HC;^z}Q=g-&5H0YNWC~Z{wUbJzV4(Y4ICff#G zSwi@ca*x3Vz88UvS!r7AI*I?cf7y?%a%D&5vw+28qL5Cm6(=7LXcO*3VHWxMt73qwOg5z~{Y`5|V`mG+?}eKxYN94|aC z9v^(E?=2hA`VGF4MH1=fvgw>9VY< ze<9?m=TS#6!re2E>ZvDmnrfD8!(tAgNbdaQ{!gL#xy0lpfk%@3tC0Rc$=2rkv&>qE{o3lS?a!45pDSLf>X6H?RaNnu#(3bTIuN8?S zo)EM-TFYT4(wH|w{K?sFs7O=hUoEO&v>ra}l@lWij)pcEZo&x@Wo4#bw!qrAyXuXD z`Pa_BRE-jg&)K-O$GHMb=y9CuPQCbnOkeBkgY^(JAxA~Q&pzr5l2$MYW!a=6kG(gt zZz5mjq`%+$pu4pCtE4BQYV&r*jHs317c?7>37HWn-xV(5v@KM?^rT@|$s2BshMq(d zy|eN|Hx1uoXASv;Ps_{i@NAVwT;&w*D6T&o#CkEM)X1BId>YBI!bO0TE6@F~M2o!n zZu@D>(T4j2?~)C{@(f|soi9Q&qCa zgjZ2@3q}}1K7n4M^#k@H)#shd7Zn1M=2~Z*ZVC$V3^HubK+8Ip?^9G= zg1VEGKV278_J9c^qfgx%aX)uMhMW7rj$1PcAA!Qv?0QW@RivsSxB0c}%#<~lnX$=0 z@Br-MSs-dcu8m%dXXZ0z`6tRXyKw**4QO&#hWUWa+G78$pDv>NO$!V7JEwhAg(t|b zZtv4r?FL%03O`h72C)z!`a*>!Fw0`sxih^Jep!~wuRWA=9^t8z+Z2SNau^ctDgaYZ- znXi%=beHcHj6sAA)hc0}@{vo5+Yd*NPeGXpY~BRw2M|NZttKrsRpv8Ds}oinWZY)& zrSR0?ZZ_T@&iieB@7Do8Yj0ckN*6KLYU->g+N)p(dP4A);5cL@%?{R0!vOZ)diC) zc6zJKt7M;QXni55F2dmlom~z|N5z|3Rw?Fe>l2+wRcio`?Vp3KHS54*Mffj<;{ags zj5>e(1pkXlX}Vk`StrLD;=ys?;NE{QF?p2ig}AugQx=!z&MkQD#K`kV1rQ2MGSn9I z!uuigQ31a*{!vCIq9(_0`Y5240VJ0yh-^QlL-_(YE?6g1XP2ZEf!bzw5@}o^&FuQ| zWMcD0SCSKwq+KA{{Bk9y_sCpZ*=|_cI&TZBVM@TLtX!>85Z#JqnU17aKZ>q*Sfe}Owj8bmhrr-30(>?-~pCWv{RhQ=QnI3}8KR(5}TtzQH3{;^> zq+I70^Vzk|YWe){{|))Dzx@LgByzX?K(*qK)Da7#$PkWd_8p7-Q*?Q)HGrLz z{8cYdlK%i`Qb-4WchJiqZr}UZ>QUB zGhTgjp9jNo&Z5(PGE#STfgeVDL!SAWMC**XgOY_pu3=l?uUOYcq^oxa9Ajip`5cXf zk0W;mfx*}f1LgylK?5NDYgsgFIO7Pvw~I0#NrU_fq>T2WIB5H}A@~E0iYyl{uZ=PH zFVZam%IM7J2ryss2DbMrNi`1DXhX%pv^nTd^o%}wrkx{JV2!l=drb^KO0l0&NsRqF zRShpR1=^i7)AQg1<9iC^tvnZFfh7x%!=dd0E)jfiW9XSZu(=4DZ%Sj#CcOPmh=AP) zh5_Wr&b;0EGQ6%dI;+k`&Nu7H*Ge<;@ibYvS4s(sm)~JINBUw83j^}51uq*uEwP+! zxhy%cvK&3N^~Sd8u>{p-Rer+IL1((kFyePJodIBYVORmOE>@L<&H|pY$0)pzE_?DooA6h4riK&?M!&laTE%W|8Qjg#{rjm@`gkjA{@`s1NZTlCPIH;upIqvb_ zy+(4`0I`H2BE|#gMhib0TNpt=s_`Z(N92iX{kFsHTWR;JG_M4_gX0KcL&yO?wvYIxV`WZny*PF{%=|V3eF&L3bJMe zr~>B|wcRV(HRVjW^5c z%To-~ijseQpB_7=Vj;+dCECo5$<$6cr)6iRJV^QnqlFQ83^(k} zbj^Wtf@~omAb$@PMvzQee*=1{AOI{ET;1srsa_V)VyN^%HPk5lurX;WoWEiwO19b-w%Bly#l9gC8Mcq!FeCU zjgP}`*?v!otO^_57MgI+B)XM}6`s70?m~IUkQ|+1_`hJ?earIosm9Hs zXhg8B1|LeNNH)C&o0;RfnZS(M)aSj3%`c%U{;T=J-GNDex%8w$yD2i zmUXgeStM$w^pv7|nFWS~ZzkJDM!&vA;g|X1&p@<4f7Ki9FhKXCE^;ZTrwFRWw}oC= zaM4WB+vL(ijcue-$I1^!3olTkQ3-qgZ~1*e3Bf;UhY~wBh5f?(f8-V0nbcEq=V>;K|K zvv2asdRFC9GG?NKvr&xobz9{EydnfyHOzBvg{O3= zg5yLsMB$OfsX6>XtD@OPaEdcQDn=i~vB1O0=!BEQkSj91QvUEP-6d2KiHZWM1|{d7 zlZ7ufM$>0w|80gmuujTYTTm6mS<_K*X4x%Gy1gU`BrJ%yRG=;o&oL1q1!1wG=ekGL zfygrgBq~8R&R^hOU+Z0PhELLl(MoD}bhOA=c{QJ^;O#8FNKu(YCSl4Q@v6|M5QdAp zkXxhI2M%xkcQs=}eTlMJ6&LWBp zM9|fPLhTy>6052AZ9rNCD?$1KcUtk~J7$}gii0Zq2IYVC3_;%mQ1O_yKkT4F-pvhz z&i_TlIgm}G2JH~eZ5CUwE(pf`;QsHCH-%=H<)KR0lJ)IJ6jOgLl4jeIq=H&*5T78ZXu)HY%z z{*>lQ;`f4ZA&9wQut@l6IzboTBD^n7r4rVwRwkzzIBSi0Qe3PnjH=#OL*+A}wtGKL zk>-ukogH6#*6PEPWW$$GA^c&KqCGtaof6ijGnevjIPWp}I@hNdBfJI?^oQdT8Cy#2 z$^|nRGGk-4r_kq2;B(^RnQU$&f#tpvS$F6Wm!Jz1KHXH1BgXq{wA?E&XS*P~vi$)& zOhO|bO0(A&yJlMcKKpY;DLx%baNXE6rWx^LTqU^D75%j#5G^kBNT7u4j)YgyABRy@ z%_^#fOpPd(2BF1b=pL*a^hrpd4jm0rqZ|f_uK#l_Gn;l{Ds-!?kb0|vOUT*LJ9XVI9;Fri%JzEbuPo62dUMN&FJ?4YX(Bm@7$h} zQbFrMjzEgfX?&%%5d{M^rNkG|CkDok5JhqbKE--=1+tl)mCZIPk!NH8?}k7A)dl&` zesO5$ktg5>_Wk-9j-qY&3-lwv^7&4$$;>!Zo?%!br_GVP349bkc~wPjnZVpNQS}coWu8kB-(1%oH5k{i3?31&6*`h zOhax76?A-az(Wr(@I7^R1H0{YGn8B)74XvjJ94xCX5wgMO$K5co-dvLurkPjepf+e zn={ceUHBsz)l1}p?6opIkaj~*1PZ&>@;N$?uE$hR1jc!}w}6?cM1n%t2jWh{K+N!L z=+olJ{BR~(J2`rp-w=fG73>o)V!ix+JN#MiKvO3fdPkldl7t+z?&_ zM->5g4aWspHXpk!1{m#DrEDu5=u`ujHu7LKwm~f)k@Z(3eWDNS2Q&J{ZGs)ZoGSFl z#0hdoB`6IC6b$|~^NFFuE2#e%_}&<954v&7oV_^pHbD+K_8W(oF(%k~gg`ws{Qlah zg!jghzXOl~U=dN;2eZ30NZH8r_)Dyv0gC&N7oxE(Si}r@sOXnu&D}7$&=`RnrcQ$P zlTesv!lW?#=Pkp#I#yL-(#WGk)(_I_AQ|XTW4F#_v^FPP%}!;qXz2xF#LY2i{4_}v zO%03T*}=HZj+U3Xw@s2Id232NUmQkeKsy30Ncbql;tRd$%n?~@bJ-xa-9+Z2uhFA$ l{a?6&aQFW_y0$5^3^vkJVSiyp0P|p+*3#F^IzhPmKLEhSw*>$I literal 0 HcmV?d00001 diff --git a/index.js b/index.js new file mode 100644 index 0000000..cb76f9c --- /dev/null +++ b/index.js @@ -0,0 +1,28 @@ +export { + default as forceNeighbourSampling +} + from "./src/neighbourSampling"; +export { + default as forceNeighbourSamplingPre +} + from "./src/neighbourSamplingPre"; +export { + default as forceNeighbourSamplingDistance +} + from "./src/neighbourSamplingDistance"; +export { + default as forceBarnesHut +} + from "./src/barnesHut"; +export { + default as tSNE +} + from "./src/t-sne"; +export { + default as forceLink +} + from "./src/link"; +export { + default as hybridSimulation +} + from "./src/hybridSimulation"; diff --git a/package.json b/package.json new file mode 100644 index 0000000..723fe2f --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "d3-neighbour-sampling", + "version": "0.0.2", + "description": "A linear time algorithm for visualizing a high-dimensional data.", + "keywords": [ + "d3", + "d3-module", + "d3-neighbour-sampling", + "force" + ], + "license": "MIT", + "main": "build/d3-neighbour-sampling.js", + "jsnext:main": "index", + "homepage": "https://github.com/sReeper/d3-neighbour-sampling", + "repository": { + "type": "git", + "url": "https://github.com/sReeper/d3-neighbour-sampling.git" + }, + "scripts": { + "pretest": "rmdir /s /q build && mkdir build && rollup -g d3-force:d3,d3-dispatch:d3,d3-quadtree:d3,d3-collection:d3 -f umd -n d3 -o build/d3-neighbour-sampling.js -- index.js", + "test": "tape 'test/**/*-test.js'", + "prepublish": "npm run test && uglifyjs build/d3-neighbour-sampling.js -c -m -o build/d3-neighbour-sampling.min.js", + "postpublish": "zip -j build/d3-neighbour-sampling.zip -- LICENSE README.md build/d3-neighbour-sampling.js build/d3-neighbour-sampling.min.js" + }, + "devDependencies": { + "rollup": "0.36", + "tape": "4", + "uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony" + }, + "dependencies": { + "d3-collection": "^1.0.3", + "d3-force": "^1.0.6", + "d3-dispatch": "^1.0.3", + "d3-quadtree": "^1.0.3" + } +} diff --git a/src/barnesHut.js b/src/barnesHut.js new file mode 100644 index 0000000..fed7583 --- /dev/null +++ b/src/barnesHut.js @@ -0,0 +1,158 @@ +import constant from "./constant"; +import jiggle from "./jiggle"; +import {x, y} from "./xy"; +import {quadtree} from "d3-quadtree"; + +/** + * The refinement of the existing Barnes-Hut implementation in D3 + * to fit the use case of the project. Previously the algorithm stored + * strength as internal node, now the random child is stored as internal + * node and the force calculations are done between the node and that internal + * object if they are sufficiently far away. + * The check to see if the nodes are far away was also changed to the one described in original Barnes-Hut paper. + * @return {force} calculated forces. + */ +export default function() { + var nodes, + node, + alpha, + distance = constant(300), + theta = 0.5; + + /** + * Constructs a quadtree at every iteration and apply the forces by visiting + * each node in a tree. + * @param {number} _ - controls the stopping of the + * particle simulations. + */ + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x, y).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) { + node = nodes[i], tree.visit(apply); + } + } + + /** + * Function used during the tree construction to fill out the nodes with + * correct data. Internal nodes acquire the random child while the leaf + * nodes accumulate forces from coincident quadrants. + * @param {quadrant} quad - node representing the quadrant in quadtree. + */ + function accumulate(quad) { + var q, d, children = []; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (var i = 0; i < 4; ++i) { + if ((q = quad[i]) && (d = q.data)) { + children.push(d); + } + } + // Choose a random child. + quad.data = children[Math.floor(Math.random() * children.length)]; + quad.x = quad.data.x; + quad.y = quad.data.y; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + } + } + + /** + * Function that applies the forces for each node. If the objects are + * far away, the approximation is made. Otherwise, forces are calculated + * directly between the nodes. + * @param {quadrant} quad - node representing the quadrant in quadtree. + * @param {number} x1 - lower x bound of the node. + * @param {number} _ - lower y bound of the node. + * @param {number} x2 - upper x bound of the node. + * @return {boolean} - true if the approximation was applied. + */ + function apply(quad, x1, _, x2) { + + var x = quad.data.x + quad.data.vx - node.x - node.vx, + y = quad.data.y + quad.data.vy - node.y - node.vy, + w = x2 - x1, + l = Math.sqrt(x * x + y * y); + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w / l < theta) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + if (quad.data) { + l = (l - +distance(node, quad.data)) / l * alpha; + x *= l, y *= l; + quad.data.vx -= x; + quad.data.vy -= y; + node.vx += x; + node.vy += y; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + } + + do if (quad.data !== node) { + l = (l - +distance(node, quad.data)) / l * alpha; + x *= l, y *= l; + quad.data.vx -= x; + quad.data.vy -= y; + node.vx += x; + node.vy += y; + } while (quad = quad.next); + } + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var totalDiffSq = 0, totalHighDistSq = 0; + for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) { + for (var j = 0; j < nodes.length; j++) { + if (i !== j) { + source = nodes[i], target = nodes[j]; + realDist = Math.hypot(target.x-source.x, target.y-source.y); + highDist = +distance(nodes[i], nodes[j]); + totalDiffSq += Math.pow(realDist-highDist, 2); + totalHighDistSq += highDist * highDist; + } + } + } + return Math.sqrt(totalDiffSq/totalHighDistSq); + } + + // API for initializing the algorithm, setting parameters and querying + // metrics. + force.initialize = function(_) { + nodes = _; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), force) : distance; + }; + + force.theta = function(_) { + return arguments.length ? (theta = _, force) : theta; + }; + + force.stress = function() { + return getStress(); + }; + + return force; +} diff --git a/src/constant.js b/src/constant.js new file mode 100644 index 0000000..5f5f1ea --- /dev/null +++ b/src/constant.js @@ -0,0 +1,8 @@ +/** + * @return a constant defined by x. + */ +export default function(x) { + return function() { + return x; + }; +} diff --git a/src/hybridSimulation.js b/src/hybridSimulation.js new file mode 100644 index 0000000..5e1a9aa --- /dev/null +++ b/src/hybridSimulation.js @@ -0,0 +1,154 @@ +import { dispatch } from "d3-dispatch"; +import constant from "./constant"; +import interpolation from "./interpolation"; +import interpolationPivots from "./interpolationPivots"; + +export default function (nodes) { + + var hybrid, + fullSimulation, + distance = constant(300), + MULTIPLIER = 50, + PIVOTS = false, + NUMPIVOTS = 3, + SAMPLE_ITERATIONS = 300, + FULL_ITERATIONS = 20, + neighbourSize = 6, + sampleSize = 3, + event = d3Dispatch.dispatch("sampleTick", "fullTick", "startFull", "end"); + + var sets = sampleFromNodes(nodes, nodes.length, Math.sqrt(nodes.length)); + var sample = sets.sample; + var remainder = sets.remainder; + var interpSubset = sampleFromNodes(sample, sample.length, Math.sqrt(sample.length)).sample; + + var sampleSimulation = d3.forceSimulation() + .alphaDecay(1 - Math.pow(0.001, 1 / SAMPLE_ITERATIONS)); + + sampleSimulation + .force("neighbourSampling", d3.forceNeighbourSampling() + .distance(function (s, t) { + return distance(s, t, props, norm) * MULTIPLIER; + }) + .neighbourSize(neighbourSize) + .sampleSize(sampleSize)) + .nodes(sample) + .on("tick", function () { + event.call("sampleTick", sampleSimulation); + }) + .on("end", ended); + + + function ended() { + if (PIVOTS) { + interpolationPivots(sample, remainder, interpSubset, NUMPIVOTS, distance); + } else { + interpolation(sample, remainder, interpSubset, distance); + } + + fullSimulation = d3.forceSimulation() + .alphaDecay(1 - Math.pow(0.001, 1 / FULL_ITERATIONS)); + + event.call("startFull", fullSimulation); + + fullSimulation + .force("neighbourSampling", d3.forceNeighbourSampling() + .distance(function (s, t) { + return distance(s, t, props, norm) * MULTIPLIER; + }) + .neighbourSize(neighbourSize) + .sampleSize(sampleSize)) + .nodes(nodes) + .on("tick", function () { + event.call("fullTick", fullSimulation); + }) + .on("end", function () { + event.call("end", fullSimulation); + }); + } + + return hybrid = { + distance: function (_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), hybrid) : distance; + }, + + stop: function () { + if (typeof sampleSimulation !== 'undefined') { + sampleSimulation.stop(); + } + if (typeof fullSimulation !== 'undefined') { + fullSimulation.stop(); + } + return hybrid; + }, + + pivots: function (_) { + return arguments.length ? (PIVOTS = _, hybrid) : PIVOTS; + }, + + numPivots: function (_) { + return arguments.length ? (NUMPIVOTS = +_, hybrid) : NUMPIVOTS; + }, + + multiplier: function (_) { + return arguments.length ? (MULTIPLIER = +_, hybrid) : MULTIPLIER; + }, + + sampleIterations: function (_) { + return arguments.length ? (SAMPLE_ITERATIONS = +_, hybrid) : SAMPLE_ITERATIONS; + }, + + fullIterations: function (_) { + return arguments.length ? (FULL_ITERATIONS = +_, hybrid) : FULL_ITERATIONS; + }, + + neighbourSize: function (_) { + return arguments.length ? (neighbourSize = +_, hybrid) : neighbourSize; + }, + + sampleSize: function (_) { + return arguments.length ? (sampleSize = +_, hybrid) : sampleSize; + }, + + on: function (name, _) { + return arguments.length > 1 ? (event.on(name, _), hybrid) : event.on(name); + }, + + sample: function (_) { + return arguments.length ? (sample = _, hybrid) : sample; + }, + + remainder: function (_) { + return arguments.length ? (remainder = _, hybrid) : remainder; + }, + + stress: function () { + return fullSimulation.force("neighbourSampling").stress(); + } + }; + +} + + +function sampleFromNodes(nodes, max, size) { + var randElements = []; + + for (var i = 0; i < size; ++i) { + var rand = nodes[Math.floor((Math.random() * max))]; + // If the rand is already in random list or in exclude list + // ignore it and get a new value. + while (randElements.includes(rand)) { + rand = nodes[Math.floor((Math.random() * max))]; + } + randElements.push(rand); + } + + var remainder = nodes.filter(function (node) { + return !randElements.includes(node); + }); + + return { + sample: randElements, + remainder: remainder + }; +} \ No newline at end of file diff --git a/src/interpolation.js b/src/interpolation.js new file mode 100644 index 0000000..43df2d0 --- /dev/null +++ b/src/interpolation.js @@ -0,0 +1,195 @@ +export default function(sampleSet, remainderSet, interpSubset, distanceFunction) { + var distance = distanceFunction; + // var distance = calculateEuclideanDistance; + + // console.log("Brute-force"); + + for (var i = 0; i < remainderSet.length; i++) { + var node = remainderSet[i], + minNode = sampleSet[0], + minDist = 0, + sampleCache = []; + + minDist = distance(node, minNode, props, norm); + + for (var j = 1, sample; j < sampleSet.length; j++) { + sample = sampleSet[j]; + if ((sample !== node) && (distance(node, sample, props, norm) < minDist)) { + minDist = distance(node, sample, props, norm); + minNode = sample; + } + } + + // console.log() + + for (var k = 0; k < interpSubset.length; k++) { + sampleCache[k] = distance(node, interpSubset[k], props, norm); + } + var radius = distance(node, minNode, props, norm); + placeNearToNearestNeighbour(node, minNode, interpSubset, sampleCache, radius); + } +} + + +function placeNearToNearestNeighbour(node, minNode, sample, sampleCache, radius) { + var + dist0 = 0.0, + dist90 = 0.0, + dist180 = 0.0, + dist270 = 0.0, + lowBound = 0.0, + highBound = 0.0; + + dist0 = sumDistToSample(node, centerPoint(0, radius, minNode.x, minNode.y), sample, sampleCache); + dist90 = sumDistToSample(node, centerPoint(90, radius, minNode.x, minNode.y), sample, sampleCache); + dist180 = sumDistToSample(node, centerPoint(180, radius, minNode.x, minNode.y), sample, sampleCache); + dist270 = sumDistToSample(node, centerPoint(270, radius, minNode.x, minNode.y), sample, sampleCache); + + // console.log(dist0, dist90, dist180, dist270); + + // Determine the closest quadrant + + if (dist0 == dist180) { + if (dist90 > dist270) + lowBound = highBound = 270; + else + lowBound = highBound = 90; + + } else if (dist90 == dist270) { + if (dist0 > dist180) + lowBound = highBound = 180; + else + lowBound = highBound = 0; + } else if (dist0 > dist180) { + if (dist90 > dist270) { + lowBound = 180; + highBound = 270; + } else { + lowBound = 90; + highBound = 180; + } + } else { + if (dist90 > dist270) { + lowBound = 270; + highBound = 360; + } else { + lowBound = 0; + highBound = 90; + } + } + + var angle = binarySearch(lowBound, highBound, minNode.x, minNode.y, radius, node, sample, sampleCache); + var newPoint = centerPoint(angle, radius, minNode.x, minNode.y); + + // console.log(newPoint); + node.x = newPoint.x; + node.y = newPoint.y; + + // for (var i = 0; i < 20; i++) { + // var forces = sumForcesToSample(node, sample, sampleCache); + // // console.log(forces); + // node.x += forces.x; + // node.y += forces.y; + // } + +} + + +function centerPoint(angle, radius, posX, posY) { + var x = posX + Math.cos(toRadians(angle) * radius); + var y = posY + Math.sin(toRadians(angle) * radius); + + return { + x: x, + y: y + }; +} + +function toRadians(degrees) { + return degrees * (Math.PI / 180); +} + +function sumDistToSample(node, point, sample, sampleCache) { + var total = 0.0; + // console.log(total, sample); + + for (var i = 0; i < sample.length; i++) { + var s = sample[i]; + var realDist = Math.hypot(s.x - point.x, s.y - point.y); + var desDist = sampleCache[i]; + total += Math.abs(realDist - desDist); + } + + return total; +} + + +function sumForcesToSample(node, sample, sampleCache) { + var x = 0, + y = 0, + // len = 0, + dist = 0, + force, + SPRING_FORCE = 0.7; + + for (var i = 0, unitX, unitY; i < sample.length; i++) { + var s = sample[i]; + if (s !== node) { + unitX = s.x - node.x; + unitY = s.y - node.y; + + // Normalize coordinates + len = Math.sqrt(unitX * unitX + unitY * unitY); + unitX /= len; + unitY /= len; + + console.log(unitX, unitY); + + var realDist = Math.sqrt(unitX * unitX + unitY * unitY); + var desDist = sampleCache[i]; + dist += realDist - desDist; + force = (SPRING_FORCE * dist); + + x += unitX * force; + y += unitY * force; + } + + x *= (1.0 / sample.length); + y *= (1.0 / sample.length); + + return { + x: x, + y: y + }; + } +} + + +function binarySearch(lb, hb, x, y, r, node, sample, sampleCache) { + while (lb <= hb) { + var mid = Math.round((lb + hb) / 2); + + if ((mid === lb) || (mid === hb)) { + if (sumDistToSample(node, centerPoint(lb, r, x, y), sample, sampleCache) >= + sumDistToSample(node, centerPoint(hb, r, x, y), sample, sampleCache)) { + return hb; + } else { + return lb; + } + } else { + var distMidLeft = sumDistToSample(node, centerPoint(mid + 1, r, x, y), sample, sampleCache); + var distMidRight = sumDistToSample(node, centerPoint(mid - 1, r, x, y), sample, sampleCache); + var distMid = sumDistToSample(node, centerPoint(mid, r, x, y), sample, sampleCache); + + if (distMid > distMidLeft) { + lb = mid + 1; + } else if (distMid > distMidRight) { + hb = mid - 1; + } else { + return mid; + } + } + } + + return -1; +} diff --git a/src/interpolationPivots.js b/src/interpolationPivots.js new file mode 100644 index 0000000..ea6cc53 --- /dev/null +++ b/src/interpolationPivots.js @@ -0,0 +1,287 @@ +export default function(sampleSet, remainderSet, interpSubset, nPivots, distanceFunction) { + var distance = distanceFunction; + + // Pivot based parent finding + + var numBuckets = Math.floor(Math.sqrt(sampleSet.length)), + numPivots = nPivots, + parents = [], + maxDists = [], + bucketWidths = [], + pivotsBuckets = []; + + console.log("Parents, pivots=", numPivots); + + var pivots = createRandomSample(sampleSet.concat(remainderSet), sampleSet.length, numPivots); + + for (var i = 0; i < numPivots; i++) { + pivotsBuckets[i] = []; + for (var j = 0; j < numBuckets; j++) { + pivotsBuckets[i][j] = []; + } + } + + // Pre-processing + var fullDists = [] + for (var i = 0; i < sampleSet.length; i++) { + fullDists[i] = []; + } + + for (var j = 0, maxDist = -1; j < numPivots; j++) { + var c1 = pivots[j]; + for (var i = 0; i < sampleSet.length; i++) { + var c2 = sampleSet[i]; + if (c1 !== c2) { + var dist = distance(c1, c2, props, norm); + // console.log(dist, c1, c2); + if (dist > maxDist) { + maxDist = dist; + } + fullDists[i][j] = dist; + } else { + fullDists[i][j] = 0.0001; + } + } + maxDists.push(maxDist); + bucketWidths.push(maxDist / numBuckets); + } + + // console.log(fullDists); + + for (var j = 0; j < numPivots; j++) { + var bucketWidth = bucketWidths[j]; + for (var i = 0; i < sampleSet.length; i++) { + var tmp = pivotsBuckets[j][Math.floor((fullDists[i][j] - 0.0001) / bucketWidth)]; + // pivotsBuckets[j][Math.floor((fullDists[i][j] - 0.0001) / bucketWidth)].push(sampleSet[i]); + // console.log(tmp, i, j, bucketWidth, Math.floor((fullDists[i][j] - 0.0001) / bucketWidth)); + tmp.push(sampleSet[i]); + } + } + + for (var i = 0; i < remainderSet.length; i++) { + var node = remainderSet[i], + minNode = sampleSet[0], + minDist = 0, + sampleCache = []; + + // Pivot based parent search + + var node = remainderSet[i]; + var clDist = Number.MAX_VALUE; + for (var p = 0; p < numPivots; p++) { + var comp = pivots[p]; + var bucketWidth = bucketWidths[p]; + if (node !== comp) { + var dist = distance(node, comp, props, norm); + var bNum = Math.floor((dist - 0.0001) / bucketWidth); + if (bNum >= numBuckets) { + bNum = numBuckets - 1; + } else if (bNum < 0) { + bNum = 0; + } + var bucketContents = pivotsBuckets[p][bNum]; + for (var w = 0; w < bucketContents.length; w++) { + var c1 = bucketContents[w]; + if (c1 != node) { + dist = distance(c1, node, props, norm); + if (dist <= clDist) { + clDist = dist; + minNode = bucketContents[w]; + } + } + } + } + } + + + for (var k = 0; k < interpSubset.length; k++) { + sampleCache[k] = distance(node, interpSubset[k], props, norm); + } + var radius = distance(node, minNode, props, norm); + placeNearToNearestNeighbour(node, minNode, interpSubset, sampleCache, radius); + } +} + + +function placeNearToNearestNeighbour(node, minNode, sample, sampleCache, radius) { + var + dist0 = 0.0, + dist90 = 0.0, + dist180 = 0.0, + dist270 = 0.0, + lowBound = 0.0, + highBound = 0.0; + + dist0 = sumDistToSample(node, centerPoint(0, radius, minNode.x, minNode.y), sample, sampleCache); + dist90 = sumDistToSample(node, centerPoint(90, radius, minNode.x, minNode.y), sample, sampleCache); + dist180 = sumDistToSample(node, centerPoint(180, radius, minNode.x, minNode.y), sample, sampleCache); + dist270 = sumDistToSample(node, centerPoint(270, radius, minNode.x, minNode.y), sample, sampleCache); + + // console.log(dist0, dist90, dist180, dist270); + + // Determine the closest quadrant + + if (dist0 == dist180) { + if (dist90 > dist270) + lowBound = highBound = 270; + else + lowBound = highBound = 90; + + } else if (dist90 == dist270) { + if (dist0 > dist180) + lowBound = highBound = 180; + else + lowBound = highBound = 0; + } else if (dist0 > dist180) { + if (dist90 > dist270) { + lowBound = 180; + highBound = 270; + } else { + lowBound = 90; + highBound = 180; + } + } else { + if (dist90 > dist270) { + lowBound = 270; + highBound = 360; + } else { + lowBound = 0; + highBound = 90; + } + } + + var angle = binarySearch(lowBound, highBound, minNode.x, minNode.y, radius, node, sample, sampleCache); + var newPoint = centerPoint(angle, radius, minNode.x, minNode.y); + + // console.log(newPoint); + node.x = newPoint.x; + node.y = newPoint.y; + + // for (var i = 0; i < 20; i++) { + // var forces = sumForcesToSample(node, sample, sampleCache); + // // console.log(forces); + // node.x += forces.x; + // node.y += forces.y; + // } + +} + + +function centerPoint(angle, radius, posX, posY) { + var x = posX + Math.cos(toRadians(angle) * radius); + var y = posY + Math.sin(toRadians(angle) * radius); + + return { + x: x, + y: y + }; +} + +function toRadians(degrees) { + return degrees * (Math.PI / 180); +} + +function sumDistToSample(node, point, sample, sampleCache) { + var total = 0.0; + // console.log(total, sample); + + for (var i = 0; i < sample.length; i++) { + var s = sample[i]; + var realDist = Math.hypot(s.x - point.x, s.y - point.y); + var desDist = sampleCache[i]; + total += Math.abs(realDist - desDist); + } + + return total; +} + + +function sumForcesToSample(node, sample, sampleCache) { + var x = 0, + y = 0, + // len = 0, + dist = 0, + force, + SPRING_FORCE = 0.7; + + for (var i = 0, unitX, unitY; i < sample.length; i++) { + var s = sample[i]; + if (s !== node) { + unitX = s.x - node.x; + unitY = s.y - node.y; + + // Normalize coordinates + len = Math.sqrt(unitX * unitX + unitY * unitY); + unitX /= len; + unitY /= len; + + console.log(unitX, unitY); + + var realDist = Math.sqrt(unitX * unitX + unitY * unitY); + var desDist = sampleCache[i]; + dist += realDist - desDist; + force = (SPRING_FORCE * dist); + + x += unitX * force; + y += unitY * force; + } + + x *= (1.0 / sample.length); + y *= (1.0 / sample.length); + + return { + x: x, + y: y + }; + } +} + +function createRandomSample(nodes, max, size) { + var randElements = []; + + for (var i = 0; i < size; ++i) { + // Stop when no new elements can be found. + if (randElements.size >= nodes.length) { + break; + } + var rand = Math.floor((Math.random() * max)); + // If the rand is already in random list or in exclude list + // ignore it and get a new value. + while (randElements.includes(rand)) { + rand = Math.floor((Math.random() * max)); + } + randElements.push(nodes[rand]); + } + + return randElements; +} + + +function binarySearch(lb, hb, x, y, r, node, sample, sampleCache) { + while (lb <= hb) { + var mid = Math.round((lb + hb) / 2); + + if ((mid === lb) || (mid === hb)) { + if (sumDistToSample(node, centerPoint(lb, r, x, y), sample, sampleCache) >= + sumDistToSample(node, centerPoint(hb, r, x, y), sample, sampleCache)) { + return hb; + } else { + return lb; + } + } else { + var distMidLeft = sumDistToSample(node, centerPoint(mid + 1, r, x, y), sample, sampleCache); + var distMidRight = sumDistToSample(node, centerPoint(mid - 1, r, x, y), sample, sampleCache); + var distMid = sumDistToSample(node, centerPoint(mid, r, x, y), sample, sampleCache); + + if (distMid > distMidLeft) { + lb = mid + 1; + } else if (distMid > distMidRight) { + hb = mid - 1; + } else { + return mid; + } + } + } + + return -1; +} diff --git a/src/jiggle.js b/src/jiggle.js new file mode 100644 index 0000000..f3ab83e --- /dev/null +++ b/src/jiggle.js @@ -0,0 +1,6 @@ +/** + * @return {number} a random number. + */ +export default function() { + return (Math.random() - 0.5) * 1e-6; +} diff --git a/src/link.js b/src/link.js new file mode 100644 index 0000000..0211c7b --- /dev/null +++ b/src/link.js @@ -0,0 +1,150 @@ +import constant from "./constant"; +import jiggle from "./jiggle"; +import {map} from "d3-collection"; + +/** + * Extended link force algorithm to include the stress metric for + * comparisons between the different algorithms. + * Everything else is the same as in D3 force module. + */ + +function index(d, i) { + return i; +} + +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; +} + +export default function(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha/* * strengths[i]*/; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = map(nodes, id), + link; + + for (i = 0, count = new Array(n); i < n; ++i) { + count[i] = 0; + } + + for (i = 0; i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + ++count[link.source.index], ++count[link.target.index]; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var m = links.length, + totalDiffSq = 0, + totalHighDistSq = 0, + link; + for (var i = 0, source, target, realDist, highDist; i < m; i++) { + link = links[i], source = link.source, target = link.target; + realDist = Math.hypot(target.x-source.x, target.y-source.y); + highDist = distances[i]; + totalDiffSq += Math.pow(realDist-highDist, 2); + totalHighDistSq += highDist * highDist; + } + return Math.sqrt(totalDiffSq/totalHighDistSq); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; + }; + + force.stress = function() { + return getStress(); + } + + return force; +} diff --git a/src/neighbourSampling.js b/src/neighbourSampling.js new file mode 100644 index 0000000..0b8f049 --- /dev/null +++ b/src/neighbourSampling.js @@ -0,0 +1,257 @@ +import constant from "./constant"; +import jiggle from "./jiggle"; + +/** + * Set the node id accessor to the specified i. + * @param {node} d - node. + * @param {accessor} i - id accessor. + * @return {accessor} - node id accessor. + */ +function index(d, i) { + return i; +} + +/** + * The implementation of Chalmers' 1996 Neighbour and Sampling algorithm. + * It uses random sampling to find the most suited neighbours from the + * data set. + * @return {force} calculated forces. + */ +export default function () { + var id = index, + neighbours = [], + samples = new Array(), + distance = constant(300), + nodes, + neighbourSize = 6, + sampleSize = 3, + freeness = 0.85, + springForce = 0.7, + dampingFactor = 0.3, + velocity, + multiplier = 50; + + /** + * Calculates the forces at each iteration between the node and the + * objects in neighbour and sample sets. + * @param {number} alpha - controls the stopping of the + * particle simulations. + */ + function force(alpha) { + velocity = 0; + for (var i = 0, n = nodes.length; i < n; ++i) { + // Randomize the samples for every node. + samples[i] = randomizeSample(i); + // Calculate the forces between node and its neighbours. + for (var [keyN, valueN] of neighbours[i]) { + setVelocity(i, keyN, valueN, alpha); + } + // Calculate the forces between node and its sample set. + for (var [keyS, valueS] of samples[i]) { + setVelocity(i, keyS, valueS, alpha); + } + // Check if there are a better neighbours in a sample array + // for each node. + findNewNeighbours(i); + } + } + + /** + * Set the velocities of the source and target nodes. + * @param {number} sourceId - source node id. + * @param {number} targetId - target node id. + * @param {number} dist - high dimensional distance between + * the two nodes. + * @param {number} alpha - controls the speed of simulation. + */ + function setVelocity(sourceId, targetId, dist, alpha) { + var source, target, x, y, l; + source = nodes[sourceId], target = nodes[targetId]; + // If x or y coordinates not defined, add some randomness. + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - dist * multiplier) / l * alpha; + x *= l, y *= l; + velocity += x + y; + // Set the calculated velocites for both nodes. + target.vx -= x; + target.vy -= y; + source.vx += x; + source.vy += y; + } + + /** + * Initialize the neighbour and sample set at the start. + */ + function initialize() { + if (!nodes) return; + + // Initialize for each node a neighbour and sample arrays + // with random values. + for (var i = 0, n = nodes.length; i < n; ++i) { + var exclude = []; // Array that keeps the indices of nodes to ignore. + exclude.push(i); + + var neighbs = createRandomSample(i, exclude, n, neighbourSize); + // Sort the neighbour set by the distances. + neighbs = new Map([...neighbs.entries()].sort(sortDistances)); + neighbours[i] = neighbs; + + exclude.concat(neighbs); + samples[i] = createRandomSample(i, exclude, n, sampleSize); + } + } + + /** + * Function that compares to map elements by its values. + * @param {object} a + * @param {object} b + * @return {number} - 0, if values are equal, positive number if b > a, + * negative otherwise. + */ + function sortDistances(a, b) { + return b[1] - a[1]; + } + + /** + * Create an array of random integers, all different, with maximum + * value max and with size elements. No elements from exlucde should + * be included. + * @param {number} index - index of current node. + * @param {array} exclude - indices of the nodes to ignore. + * @param {number} max - maximum value. + * @param {number} size - the number of elements in map to return. + * @return {map} - a created map that contains random elements from + * data set. + */ + function createRandomSample(index, exclude, max, size) { + var randElements = new Map(); + + for (var i = 0; i < size; ++i) { + // Stop when no new elements can be found. + if (randElements.size + exclude.length >= nodes.length) { + break; + } + var rand = Math.floor((Math.random() * max)); + // If the rand is already in random list or in exclude list + // ignore it and get a new value. + while (randElements.has(rand) || exclude.includes(rand)) { + rand = Math.floor((Math.random() * max)); + } + randElements.set(rand, +distance(nodes[index], nodes[rand])); + } + + return randElements; + } + + /** + * Creates a new map of random numbers to be used by the samples list. + * @param {number} index - index of current node. + * @return {map} - map that contains random elements from data set. + */ + function randomizeSample(index) { + // Ignore the current neighbours of the node and itself. + var exclude = [index]; + exclude = exclude.concat(Array.from(neighbours[index].keys())); + return createRandomSample(index, exclude, nodes.length, sampleSize); + } + + /** + * Compares the elements from sample set to the neighbour set and + * replaces the elements from neighbour set if better neighbours are + * found in sample set. + * @param {number} index - index of current node. + */ + function findNewNeighbours(index) { + var sample = samples[index]; + + for (var [key, value] of sample) { + var neighbMax = neighbours[index].entries().next().value; + + // Check if a value from sample could be a better neighbour + // if so, replace it. + if (value < neighbMax[1]) { + neighbours[index].delete(neighbMax[0]); + neighbours[index].set(key, value) + neighbours[index] = new Map([...neighbours[index].entries()].sort(sortDistances)); + } + } + } + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var totalDiffSq = 0, totalHighDistSq = 0; + for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) { + for (var j = 0; j < nodes.length; j++) { + if (i !== j) { + source = nodes[i], target = nodes[j]; + realDist = Math.hypot(target.x - source.x, target.y - source.y); + highDist = +distance(source, target); + totalDiffSq += Math.pow(realDist - highDist, 2); + totalHighDistSq += highDist * highDist; + } + } + } + return Math.sqrt(totalDiffSq / totalHighDistSq); + } + + /** + * Calculates the average velocity of the force calculation at the + * current iteration. + * @return {number} - average velocity. + */ + function getAvgVelocity() { + return velocity / ((neighbourSize + sampleSize) * nodes.length); + } + + // API for initializing the algorithm, setting parameters and querying + // metrics. + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.id = function (_) { + return arguments.length ? (id = _, force) : id; + }; + + force.neighbourSize = function (_) { + return arguments.length ? (neighbourSize = +_, force) : neighbourSize; + }; + + force.sampleSize = function (_) { + return arguments.length ? (sampleSize = +_, force) : sampleSize; + }; + + force.distance = function (_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), force) : distance; + }; + + force.stress = function () { + return getStress(); + }; + + force.velocity = function () { + return getAvgVelocity(); + }; + + force.freeness = function (_) { + return arguments.length ? (freeness = +_, force) : freeness; + }; + + force.nodeNeighbours = function (_) { + return arguments.length ? neighbours[+_] : []; + }; + + force.multiplier = function (_) { + return arguments.length ? (multiplier = +_, force) : multiplier; + }; + + return force; +} diff --git a/src/neighbourSamplingDistance.js b/src/neighbourSamplingDistance.js new file mode 100644 index 0000000..75a386e --- /dev/null +++ b/src/neighbourSamplingDistance.js @@ -0,0 +1,300 @@ +import constant from "./constant"; +import jiggle from "./jiggle"; + +/** + * Set the node id accessor to the specified i. + * @param {node} d - node. + * @param {accessor} i - id accessor. + * @return {accessor} - node id accessor. + */ +function index(d, i) { + return i; +} + +/** + * The implementation of Chalmers' 1996 Neighbour and Sampling algorithm. + * It uses random sampling to find the most suited neighbours from the + * data set. + * @return {force} calculated forces. + */ +export default function () { + var id = index, + neighbours = [], + samples = new Array(), + distance = constant(300), + distanceRange = 10, + nodes, + neighbourSize = 6, + sampleSize = 3, + freeness = 0.85, + springForce = 0.7, + dampingFactor = 0.3, + velocity, + multiplier = 50; + + /** + * Calculates the forces at each iteration between the node and the + * objects in neighbour and sample sets. + * @param {number} alpha - controls the stopping of the + * particle simulations. + */ + function force(alpha) { + velocity = 0; + for (var i = 0, n = nodes.length; i < n; ++i) { + // Randomize the samples for every node. + samples[i] = randomizeSample(i); + // Calculate the forces between node and its neighbours. + for (var [keyN, valueN] of neighbours[i]) { + setVelocity(i, keyN, valueN, alpha); + } + // Calculate the forces between node and its sample set. + for (var [keyS, valueS] of samples[i]) { + setVelocity(i, keyS, valueS, alpha); + } + // Check if there are a better neighbours in a sample array + // for each node. + findNewNeighbours(i); + } + } + + /** + * Set the velocities of the source and target nodes. + * @param {number} sourceId - source node id. + * @param {number} targetId - target node id. + * @param {number} dist - high dimensional distance between + * the two nodes. + * @param {number} alpha - controls the speed of simulation. + */ + function setVelocity(sourceId, targetId, dist, alpha) { + var source, target, x, y, l; + source = nodes[sourceId], target = nodes[targetId]; + // If x or y coordinates not defined, add some randomness. + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - dist * multiplier) / l * alpha; + x *= l, y *= l; + velocity += x + y; + // Set the calculated velocites for both nodes. + target.vx -= x; + target.vy -= y; + source.vx += x; + source.vy += y; + } + + /** + * Initialize the neighbour and sample set at the start. + */ + function initialize() { + if (!nodes) return; + + // Initialize for each node a neighbour and sample arrays + // with random values. + for (var i = 0, n = nodes.length; i < n; ++i) { + var exclude = []; // Array that keeps the indices of nodes to ignore. + exclude.push(i); + + var neighbs = createRandomNeighbours(i, exclude, n, neighbourSize); + // Sort the neighbour set by the distances. + neighbs = new Map([...neighbs.entries()].sort(sortDistances)); + neighbours[i] = neighbs; + + exclude.concat(neighbs); + samples[i] = createRandomSample(i, exclude, n, sampleSize); + } + } + + /** + * Function that compares to map elements by its values. + * @param {object} a + * @param {object} b + * @return {number} - 0, if values are equal, positive number if b > a, + * negative otherwise. + */ + function sortDistances(a, b) { + return b[1] - a[1]; + } + + /** + * Create an array of random integers, all different, with maximum + * value max and with size elements. No elements from exlucde should + * be included. + * @param {number} index - index of current node. + * @param {array} exclude - indices of the nodes to ignore. + * @param {number} max - maximum value. + * @param {number} size - the number of elements in map to return. + * @return {map} - a created map that contains random elements from + * data set. + */ + function createRandomNeighbours(index, exclude, max, size) { + var randElements = new Map(); + var triedElements = 0; + + while ((randElements.size < size) && (randElements.size + exclude.length + triedElements < nodes.length)) { + var rand = Math.floor((Math.random() * max)); + // If the rand is already in random list or in exclude list + // ignore it and get a new value. + while (randElements.has(rand) || exclude.includes(rand)) { + rand = Math.floor((Math.random() * max)); + } + var dist = +distance(nodes[index], nodes[rand]); + if (dist <= distanceRange) { + randElements.set(rand, dist); + } else { + triedElements++; + } + } + + return randElements; + } + + + function createRandomSample(index, exclude, max, size) { + var randElements = new Map(); + + for (var i = 0; i < size; ++i) { + // Stop when no new elements can be found. + if (randElements.size + exclude.length >= nodes.length) { + break; + } + var rand = Math.floor((Math.random() * max)); + // If the rand is already in random list or in exclude list + // ignore it and get a new value. + while (randElements.has(rand) || exclude.includes(rand)) { + rand = Math.floor((Math.random() * max)); + } + randElements.set(rand, +distance(nodes[index], nodes[rand])); + } + + return randElements; + } + + /** + * Creates a new map of random numbers to be used by the samples list. + * @param {number} index - index of current node. + * @return {map} - map that contains random elements from data set. + */ + function randomizeSample(index) { + // Ignore the current neighbours of the node and itself. + var exclude = [index]; + exclude = exclude.concat(Array.from(neighbours[index].keys())); + return createRandomSample(index, exclude, nodes.length, sampleSize); + } + + /** + * Compares the elements from sample set to the neighbour set and + * replaces the elements from neighbour set if better neighbours are + * found in sample set. + * @param {number} index - index of current node. + */ + function findNewNeighbours(index) { + var sample = samples[index]; + + if (neighbours[index].size > 0) { + for (var [key, value] of sample) { + var neighbMax = neighbours[index].entries().next().value; + + // Check if a value from sample could be a better neighbour + // if so, replace it. + if (value < neighbMax[1] && value <= distanceRange) { + neighbours[index].delete(neighbMax[0]); + neighbours[index].set(key, value) + neighbours[index] = new Map([...neighbours[index].entries()].sort(sortDistances)); + } + } + } + } + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var totalDiffSq = 0, totalHighDistSq = 0; + for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) { + for (var j = 0; j < nodes.length; j++) { + if (i !== j) { + source = nodes[i], target = nodes[j]; + realDist = Math.hypot(target.x - source.x, target.y - source.y); + highDist = +distance(source, target) * multiplier; + totalDiffSq += Math.pow(realDist - highDist, 2); + totalHighDistSq += highDist * highDist; + } + } + } + return Math.sqrt(totalDiffSq / totalHighDistSq); + } + + /** + * Calculates the average velocity of the force calculation at the + * current iteration. + * @return {number} - average velocity. + */ + function getAvgVelocity() { + return velocity / ((neighbourSize + sampleSize) * nodes.length); + } + + + function getDistributionData() { + var d = []; + for (var i = 0; i < nodes.length; i++) { + d.push({ "index": i, "size": neighbours[i].size }); + } + return { "maxSize": neighbourSize, "l": nodes.length, "distribution": d }; + } + + // API for initializing the algorithm, setting parameters and querying + // metrics. + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.id = function (_) { + return arguments.length ? (id = _, force) : id; + }; + + force.neighbourSize = function (_) { + return arguments.length ? (neighbourSize = +_, force) : neighbourSize; + }; + + force.sampleSize = function (_) { + return arguments.length ? (sampleSize = +_, force) : sampleSize; + }; + + force.distance = function (_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), force) : distance; + }; + + force.stress = function () { + return getStress(); + }; + + force.velocity = function () { + return getAvgVelocity(); + }; + + force.freeness = function (_) { + return arguments.length ? (freeness = +_, force) : freeness; + }; + + force.distanceRange = function (_) { + return arguments.length ? (distanceRange = +_, force) : distanceRange; + }; + + force.multiplier = function (_) { + return arguments.length ? (multiplier = +_, initialize(), force) : multiplier; + }; + + force.nodeNeighbours = function (_) { + return arguments.length ? neighbours[+_] : neighbours; + }; + + force.distributionData = function () { + return getDistributionData(); + }; + + return force; +} diff --git a/src/neighbourSamplingPre.js b/src/neighbourSamplingPre.js new file mode 100644 index 0000000..82c68ae --- /dev/null +++ b/src/neighbourSamplingPre.js @@ -0,0 +1,197 @@ +import constant from "./constant"; +import jiggle from "./jiggle"; + +/** + * Set the node id accessor to the specified i. + * @param {node} d - node. + * @param {accessor} i - id accessor. + * @return {accessor} - node id accessor. + */ +function index(d, i) { + return i; +} + +/** + * The implementation of Chalmers' 1996 Neighbour and Sampling algorithm. + * It uses random sampling to find the most suited neighbours from the + * data set. + * @return {force} calculated forces. + */ +export default function () { + var id = index, + neighbours = [], + worst = [], + samples = new Array(), + distance = constant(300), + nodes, + neighbourSize = 6, + sampleSize = 3, + freeness = 0.85, + springForce = 0.7, + dampingFactor = 0.3; + + /** + * Calculates the forces at each iteration between the node and the + * objects in neighbour and sample sets. + * @param {number} alpha - controls the stopping of the + * particle simulations. + */ + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + // Randomize the samples for every node. + // Calculate the forces between node and its neighbours. + for (var [keyN, valueN] of neighbours[i]) { + setVelocity(i, keyN, valueN, alpha); + } + // Calculate the forces between node and its sample set. + // for (var [keyS, valueS] of worst[i]) { + // setVelocity(i, keyS, valueS, alpha); + // } + } + } + + /** + * Set the velocities of the source and target nodes. + * @param {number} sourceId - source node id. + * @param {number} targetId - target node id. + * @param {number} dist - high dimensional distance between + * the two nodes. + * @param {number} alpha - controls the speed of simulation. + */ + function setVelocity(sourceId, targetId, dist, alpha) { + var source, target, x, y, l; + source = nodes[sourceId], target = nodes[targetId]; + // If x or y coordinates not defined, add some randomness. + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - dist) / l * alpha; + x *= l, y *= l; + // Set the calculated velocites for both nodes. + target.vx -= x; + target.vy -= y; + source.vx += x; + source.vy += y; + } + + /** + * Initialize the neighbour and sample set at the start. + */ + function initialize() { + if (!nodes) return; + + findNeighbours(); + } + + /** + * Function that compares to map elements by its values. + * @param {object} a + * @param {object} b + * @return {number} - 0, if values are equal, positive number if b > a, + * negative otherwise. + */ + function sortDistances(a, b) { + return b[1] - a[1]; + } + + + function findNeighbours() { + // Initialize for each node a neighbour and sample arrays + // with random values. + for (var i = 0, n = nodes.length; i < n; ++i) { + neighbours[i] = new Map(); + for (var j = 0; j < n; j++) { + if (i !== j) { + var dist = +distance(nodes[i], nodes[j]); + + if (neighbours[i].size < neighbourSize) { + neighbours[i].set(j, dist); + neighbours[i] = new Map([...neighbours[i].entries()].sort(sortDistances)); + } else { + var neighbMax = neighbours[i].entries().next().value; + + if (dist < neighbMax[1]) { + neighbours[i].delete(neighbMax[0]); + neighbours[i].set(j, dist); + neighbours[i] = new Map([...neighbours[i].entries()].sort(sortDistances)); + } + + } + } + } + } + } + + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var totalDiffSq = 0, totalHighDistSq = 0; + for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) { + for (var j = 0; j < nodes.length; j++) { + if (i !== j) { + source = nodes[i], target = nodes[j]; + realDist = Math.hypot(target.x - source.x, target.y - source.y); + highDist = +distance(source, target); + totalDiffSq += Math.pow(realDist - highDist, 2); + totalHighDistSq += highDist * highDist; + } + } + } + return Math.sqrt(totalDiffSq / totalHighDistSq); + } + + /** + * Calculates the average velocity of the force calculation at the + * current iteration. + * @return {number} - average velocity. + */ + function getAvgVelocity() { + return velocity / ((neighbourSize + sampleSize) * nodes.length); + } + + // API for initializing the algorithm, setting parameters and querying + // metrics. + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.id = function (_) { + return arguments.length ? (id = _, force) : id; + }; + + force.neighbourSize = function (_) { + return arguments.length ? (neighbourSize = +_, force) : neighbourSize; + }; + + force.sampleSize = function (_) { + return arguments.length ? (sampleSize = +_, force) : sampleSize; + }; + + force.distance = function (_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), force) : distance; + }; + + force.stress = function () { + return getStress(); + }; + + force.velocity = function () { + return getAvgVelocity(); + }; + + force.freeness = function (_) { + return arguments.length ? (freeness = +_, force) : freeness; + }; + + force.nodeNeighbours = function (_) { + return arguments.length ? neighbours[+_] : []; + }; + + return force; +} diff --git a/src/t-sne.js b/src/t-sne.js new file mode 100644 index 0000000..996bf18 --- /dev/null +++ b/src/t-sne.js @@ -0,0 +1,374 @@ +import constant from "./constant"; + +/** + * Set the node id accessor to the specified i. + * @param {node} d - node. + * @param {accessor} i - id accessor. + * @return {accessor} - node id accessor. + */ +function index(d, i) { + return i; +} + +/** + * t-SNE implementation in D3 by using the code existing in tsnejs + * (https://github.com/karpathy/tsnejs) to compute the solution. + */ +export default function() { + var id = index, + distance = constant(300), + nodes, + perplexity = 30, + learningRate = 10, + iteration = 0, + dim = 2, + N, // length of the nodes. + P, // probability matrix. + Y, // solution. + gains, + ystep; + + /** + * Make a step in t-SNE algorithm and set the velocities for the nodes + * to accumulate the values from solution. + */ + function force() { + // Make a step at each iteration. + step(); + var solution = getSolution(); + + // Set the velocity for each node using the solution. + for (var i = 0; i < nodes.length; i++) { + nodes[i].vx += solution[i][0]; + nodes[i].vy += solution[i][1]; + } + } + + /** + * Calculates the random number from Gaussian distribution. + * @return {number} random number. + */ + function gaussRandom() { + let u = 2 * Math.random() - 1; + let v = 2 * Math.random() - 1; + let r = u * u + v * v; + if (r == 0 || r > 1) return gaussRandom(); + return u * Math.sqrt(-2 * Math.log(r) / r); + } + + /** + * Return the normalized number. + * @return {number} normalized random number from Gaussian distribution. + */ + function randomN() { + return gaussRandom() * 1e-4; + } + + function sign(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + + /** + * Create an array of length n filled with zeros. + * @param {number} n - length of array. + * @return {Float64Array} - array of zeros with length n. + */ + function zeros(n) { + if (typeof(n) === 'undefined' || isNaN(n)) { + return []; + } + return new Float64Array(n); // typed arrays are faster + } + + // Returns a 2d array of random numbers + /** + * Creates a 2d array filled with random numbers. + * @param {number} n - rows. + * @param {number} d - columns. + * @return {array} - 2d array + */ + function random2d(n, d) { + var x = []; + for (var i = 0; i < n; i++) { + var y = []; + for (var j = 0; j < d; j++) { + y.push(randomN()); + } + x.push(y); + } + return x; + } + + /** + * Compute the probability matrix using the provided data. + * @param {array} data - nodes. + * @param {number} perplexity - used to calculate entropy of distribution. + * @param {number} tol - limit for entropy difference. + * @return {2d array} - 2d matrix containing probabilities. + */ + function d2p(data, perplexity, tol) { + N = Math.floor(data.length); + var Htarget = Math.log(perplexity); // target entropy of distribution. + var P1 = zeros(N * N); // temporary probability matrix. + + var prow = zeros(N); // a temporary storage compartment. + for (var i = 0; i < N; i++) { + var betamin = -Infinity; + var betamax = Infinity; + var beta = 1; // initial value of precision. + var done = false; + var maxtries = 50; + + // Perform binary search to find a suitable precision beta + // so that the entropy of the distribution is appropriate. + var num = 0; + while (!done) { + // Compute entropy and kernel row with beta precision. + var psum = 0.0; + for (var j = 0; j < N; j++) { + var pj = Math.exp(-distance(data[i], data[j]) * beta); + // Ignore the diagonals + if (i === j) { + pj = 0; + } + prow[j] = pj; + psum += pj; + } + // Normalize p and compute entropy. + var Hhere = 0.0; + for (j = 0; j < N; j++) { + if (psum == 0) { + pj = 0; + } else { + pj = prow[j] / psum; + } + prow[j] = pj; + if (pj > 1e-7) { + Hhere -= pj * Math.log(pj); + } + } + + // Adjust beta based on result. + if (Hhere > Htarget) { + // Entropy was too high (distribution too diffuse) + // so we need to increase the precision for more peaky distribution. + betamin = beta; // move up the bounds. + if (betamax === Infinity) { + beta = beta * 2; + } else { + beta = (beta + betamax) / 2; + } + + } else { + // Converse case. Make distrubtion less peaky. + betamax = beta; + if (betamin === -Infinity) { + beta = beta / 2; + } else { + beta = (beta + betamin) / 2; + } + } + + // Stopping conditions: too many tries or got a good precision. + num++; + if (Math.abs(Hhere - Htarget) < tol || num >= maxtries) { + done = true; + } + } + + // Copy over the final prow to P1 at row i + for (j = 0; j < N; j++) { + P1[i * N + j] = prow[j]; + } + + } + + // Symmetrize P and normalize it to sum to 1 over all ij + var Pout = zeros(N * N); + var N2 = N * 2; + for (i = 0; i < N; i++) { + for (j = 0; j < N; j++) { + Pout[i * N + j] = Math.max((P1[i * N + j] + P1[j * N + i]) / N2, 1e-100); + } + } + return Pout; + } + + /** + * Initialize a starting (random) solution. + */ + function initSolution() { + Y = random2d(N, dim); + // Step gains to accelerate progress in unchanging directions. + gains = random2d(N, dim, 1.0); + // Momentum accumulator. + ystep = random2d(N, dim, 0.0); + iteration = 0; + } + + /** + * @return {2d array} the solution. + */ + function getSolution() { + return Y; + } + + /** + * Do a single step (iteration) for the layout. + * @return {number} the current cost. + */ + function step() { + iteration += 1; + + var cg = costGrad(Y); // Evaluate gradient. + var cost = cg.cost; + var grad = cg.grad; + + // Perform gradient step. + var ymean = zeros(dim); + for (var i = 0; i < N; i++) { + for (var d = 0; d < dim; d++) { + var gid = grad[i][d]; + var sid = ystep[i][d]; + var gainid = gains[i][d]; + + // Compute gain update. + var newgain = sign(gid) === sign(sid) ? gainid * 0.8 : gainid + 0.2; + if (newgain < 0.01) { + newgain = 0.01; + } + gains[i][d] = newgain; + + // Compute momentum step direction. + var momval = iteration < 250 ? 0.5 : 0.8; + var newsid = momval * sid - learningRate * newgain * grad[i][d]; + ystep[i][d] = newsid; + + // Do the step. + Y[i][d] += newsid; + + // Accumulate mean so that we can center later. + ymean[d] += Y[i][d]; + } + } + + // Reproject Y to have the zero mean. + for (i = 0; i < N; i++) { + for (d = 0; d < dim; d++) { + Y[i][d] -= ymean[d] / N; + } + } + return cost; + } + + /** + * Calculate the cost and the gradient. + * @param {2d array} Y - the current solution to evaluate. + * @return {object} that contains a cost and a gradient. + */ + function costGrad(Y) { + + var pmul = iteration < 100 ? 4 : 1; + + // Compute current Q distribution, unnormalized first. + var Qu = zeros(N * N); + var qsum = 0.0; + for (var i = 0; i < N; i++) { + for (var j = i + 1; j < N; j++) { + var dsum = 0.0; + for (var d = 0; d < dim; d++) { + var dhere = Y[i][d] - Y[j][d]; + dsum += dhere * dhere; + } + var qu = 1.0 / (1.0 + dsum); // Student t-distribution. + Qu[i * N + j] = qu; + Qu[j * N + i] = qu; + qsum += 2 * qu; + } + } + // Normalize Q distribution to sum to 1. + var NN = N * N; + var Q = zeros(NN); + for (var q = 0; q < NN; q++) { + Q[q] = Math.max(Qu[q] / qsum, 1e-100); + } + + var cost = 0.0; + var grad = []; + for (i = 0; i < N; i++) { + var gsum = new Array(dim); // Initialize gradiet for point i. + for (d = 0; d < dim; d++) { + gsum[d] = 0.0; + } + for (j = 0; j < N; j++) { + // Accumulate the cost. + cost += -P[i * N + j] * Math.log(Q[i * N + j]); + var premult = 4 * (pmul * P[i * N + j] - Q[i * N + j]) * Qu[i * N + j]; + for (d = 0; d < dim; d++) { + gsum[d] += premult * (Y[i][d] - Y[j][d]); + } + } + grad.push(gsum); + } + + return { + cost: cost, + grad: grad + }; + } + + /** + * Calculates the stress. Basically, it computes the difference between + * high dimensional distance and real distance. The lower the stress is, + * the better layout. + * @return {number} - stress of the layout. + */ + function getStress() { + var totalDiffSq = 0, + totalHighDistSq = 0; + for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) { + for (var j = 0; j < nodes.length; j++) { + if (i !== j) { + source = nodes[i], target = nodes[j]; + realDist = Math.hypot(target.x - source.x, target.y - source.y); + highDist = +distance(nodes[i], nodes[j]); + totalDiffSq += Math.pow(realDist - highDist, 2); + totalHighDistSq += highDist * highDist; + } + } + } + return Math.sqrt(totalDiffSq / totalHighDistSq); + } + + // API for initializing the algorithm, setting parameters and querying + // metrics. + force.initialize = function(_) { + nodes = _; + N = nodes.length; + // Initialize the probability matrix. + P = d2p(nodes, perplexity, 1e-4); + initSolution(); + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), force) : distance; + }; + + force.stress = function() { + return getStress(); + }; + + force.learningRate = function(_) { + return arguments.length ? (learningRate = +_, force) : learningRate; + }; + + force.perplexity = function(_) { + return arguments.length ? (perplexity = +_, force) : perplexity; + }; + + return force; +} diff --git a/src/xy.js b/src/xy.js new file mode 100644 index 0000000..137b41d --- /dev/null +++ b/src/xy.js @@ -0,0 +1,13 @@ +/** + * @return x value of a node + */ +export function x(d) { + return d.x; +} + +/** + * @return y value of a node + */ +export function y(d) { + return d.y; +} \ No newline at end of file