UNPKG

dygraphs

Version:

dygraphs is a fast, flexible open source JavaScript charting library.

154 lines (142 loc) 19.2 kB
"use strict"; /** * @license * Part of dygraphs, see top-level LICENSE.txt file * MIT-licenced: https://opensource.org/license/MIT */ /* loader wrapper to allow browser use and ES6 imports */ (function _extras_smoothPlotter_closure() { 'use strict'; var Dygraph; if (window.Dygraph) { Dygraph = window.Dygraph; } else if (typeof module !== 'undefined') { Dygraph = require('../dygraph'); if (typeof Dygraph.NAME === 'undefined' && typeof Dygraph["default"] !== 'undefined') Dygraph = Dygraph["default"]; } /* end of loader wrapper header */ /** * Given three sequential points, p0, p1 and p2, find the left and right * control points for p1. * * The three points are expected to have x and y properties. * * The alpha parameter controls the amount of smoothing. * If α=0, then both control points will be the same as p1 (i.e. no smoothing). * * Returns [l1x, l1y, r1x, r1y] * * It's guaranteed that the line from (l1x, l1y)-(r1x, r1y) passes through p1. * Unless allowFalseExtrema is set, then it's also guaranteed that: * l1y ∈ [p0.y, p1.y] * r1y ∈ [p1.y, p2.y] * * The basic algorithm is: * 1. Put the control points l1 and r1 α of the way down (p0, p1) and (p1, p2). * 2. Shift l1 and r2 so that the line l1–r1 passes through p1 * 3. Adjust to prevent false extrema while keeping p1 on the l1–r1 line. * * This is loosely based on the HighCharts algorithm. */ function getControlPoints(p0, p1, p2, opt_alpha, opt_allowFalseExtrema) { var alpha = opt_alpha !== undefined ? opt_alpha : 1 / 3; // 0=no smoothing, 1=crazy smoothing var allowFalseExtrema = opt_allowFalseExtrema || false; if (!p2) { return [p1.x, p1.y, null, null]; } // Step 1: Position the control points along each line segment. var l1x = (1 - alpha) * p1.x + alpha * p0.x, l1y = (1 - alpha) * p1.y + alpha * p0.y, r1x = (1 - alpha) * p1.x + alpha * p2.x, r1y = (1 - alpha) * p1.y + alpha * p2.y; // Step 2: shift the points up so that p1 is on the l1–r1 line. if (l1x != r1x) { // This can be derived w/ some basic algebra. var deltaY = p1.y - r1y - (p1.x - r1x) * (l1y - r1y) / (l1x - r1x); l1y += deltaY; r1y += deltaY; } // Step 3: correct to avoid false extrema. if (!allowFalseExtrema) { if (l1y > p0.y && l1y > p1.y) { l1y = Math.max(p0.y, p1.y); r1y = 2 * p1.y - l1y; } else if (l1y < p0.y && l1y < p1.y) { l1y = Math.min(p0.y, p1.y); r1y = 2 * p1.y - l1y; } if (r1y > p1.y && r1y > p2.y) { r1y = Math.max(p1.y, p2.y); l1y = 2 * p1.y - r1y; } else if (r1y < p1.y && r1y < p2.y) { r1y = Math.min(p1.y, p2.y); l1y = 2 * p1.y - r1y; } } return [l1x, l1y, r1x, r1y]; } // i.e. is none of (null, undefined, NaN) function isOK(x) { return !!x && !isNaN(x); } ; // A plotter which uses splines to create a smooth curve. // See tests/plotters.html for a demo. // Can be controlled via smoothPlotter.smoothing function smoothPlotter(e) { var ctx = e.drawingContext, points = e.points; ctx.beginPath(); ctx.moveTo(points[0].canvasx, points[0].canvasy); // right control point for previous point var lastRightX = points[0].canvasx, lastRightY = points[0].canvasy; for (var i = 1; i < points.length; i++) { var p0 = points[i - 1], p1 = points[i], p2 = points[i + 1]; p0 = p0 && isOK(p0.canvasy) ? p0 : null; p1 = p1 && isOK(p1.canvasy) ? p1 : null; p2 = p2 && isOK(p2.canvasy) ? p2 : null; if (p0 && p1) { var controls = getControlPoints({ x: p0.canvasx, y: p0.canvasy }, { x: p1.canvasx, y: p1.canvasy }, p2 && { x: p2.canvasx, y: p2.canvasy }, smoothPlotter.smoothing); // Uncomment to show the control points: // ctx.lineTo(lastRightX, lastRightY); // ctx.lineTo(controls[0], controls[1]); // ctx.lineTo(p1.canvasx, p1.canvasy); lastRightX = lastRightX !== null ? lastRightX : p0.canvasx; lastRightY = lastRightY !== null ? lastRightY : p0.canvasy; ctx.bezierCurveTo(lastRightX, lastRightY, controls[0], controls[1], p1.canvasx, p1.canvasy); lastRightX = controls[2]; lastRightY = controls[3]; } else if (p1) { // We're starting again after a missing point. ctx.moveTo(p1.canvasx, p1.canvasy); lastRightX = p1.canvasx; lastRightY = p1.canvasy; } else { lastRightX = lastRightY = null; } } ctx.stroke(); } smoothPlotter.smoothing = 1 / 3; smoothPlotter._getControlPoints = getControlPoints; // for testing // older versions exported a global. // This will be removed in the future. // The preferred way to access smoothPlotter is via Dygraph.smoothPlotter. window.smoothPlotter = smoothPlotter; Dygraph.smoothPlotter = smoothPlotter; /* closure and loader wrapper */ Dygraph._require.add('dygraphs/src/extras/smooth-plotter.js', /* exports */{}); })(); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXh0cmFzX3Ntb290aFBsb3R0ZXJfY2xvc3VyZSIsIkR5Z3JhcGgiLCJ3aW5kb3ciLCJtb2R1bGUiLCJyZXF1aXJlIiwiTkFNRSIsImdldENvbnRyb2xQb2ludHMiLCJwMCIsInAxIiwicDIiLCJvcHRfYWxwaGEiLCJvcHRfYWxsb3dGYWxzZUV4dHJlbWEiLCJhbHBoYSIsInVuZGVmaW5lZCIsImFsbG93RmFsc2VFeHRyZW1hIiwieCIsInkiLCJsMXgiLCJsMXkiLCJyMXgiLCJyMXkiLCJkZWx0YVkiLCJNYXRoIiwibWF4IiwibWluIiwiaXNPSyIsImlzTmFOIiwic21vb3RoUGxvdHRlciIsImUiLCJjdHgiLCJkcmF3aW5nQ29udGV4dCIsInBvaW50cyIsImJlZ2luUGF0aCIsIm1vdmVUbyIsImNhbnZhc3giLCJjYW52YXN5IiwibGFzdFJpZ2h0WCIsImxhc3RSaWdodFkiLCJpIiwibGVuZ3RoIiwiY29udHJvbHMiLCJzbW9vdGhpbmciLCJiZXppZXJDdXJ2ZVRvIiwic3Ryb2tlIiwiX2dldENvbnRyb2xQb2ludHMiLCJfcmVxdWlyZSIsImFkZCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHRyYXMvc21vb3RoLXBsb3R0ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogUGFydCBvZiBkeWdyYXBocywgc2VlIHRvcC1sZXZlbCBMSUNFTlNFLnR4dCBmaWxlXG4gKiBNSVQtbGljZW5jZWQ6IGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZS9NSVRcbiAqL1xuXG4vKiBsb2FkZXIgd3JhcHBlciB0byBhbGxvdyBicm93c2VyIHVzZSBhbmQgRVM2IGltcG9ydHMgKi9cbihmdW5jdGlvbiBfZXh0cmFzX3Ntb290aFBsb3R0ZXJfY2xvc3VyZSgpIHtcbid1c2Ugc3RyaWN0JztcbnZhciBEeWdyYXBoO1xuaWYgKHdpbmRvdy5EeWdyYXBoKSB7XG4gIER5Z3JhcGggPSB3aW5kb3cuRHlncmFwaDtcbn0gZWxzZSBpZiAodHlwZW9mKG1vZHVsZSkgIT09ICd1bmRlZmluZWQnKSB7XG4gIER5Z3JhcGggPSByZXF1aXJlKCcuLi9keWdyYXBoJyk7XG4gIGlmICh0eXBlb2YoRHlncmFwaC5OQU1FKSA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mKER5Z3JhcGguZGVmYXVsdCkgIT09ICd1bmRlZmluZWQnKVxuICAgIER5Z3JhcGggPSBEeWdyYXBoLmRlZmF1bHQ7XG59XG4vKiBlbmQgb2YgbG9hZGVyIHdyYXBwZXIgaGVhZGVyICovXG5cbi8qKlxuICogR2l2ZW4gdGhyZWUgc2VxdWVudGlhbCBwb2ludHMsIHAwLCBwMSBhbmQgcDIsIGZpbmQgdGhlIGxlZnQgYW5kIHJpZ2h0XG4gKiBjb250cm9sIHBvaW50cyBmb3IgcDEuXG4gKlxuICogVGhlIHRocmVlIHBvaW50cyBhcmUgZXhwZWN0ZWQgdG8gaGF2ZSB4IGFuZCB5IHByb3BlcnRpZXMuXG4gKlxuICogVGhlIGFscGhhIHBhcmFtZXRlciBjb250cm9scyB0aGUgYW1vdW50IG9mIHNtb290aGluZy5cbiAqIElmIM6xPTAsIHRoZW4gYm90aCBjb250cm9sIHBvaW50cyB3aWxsIGJlIHRoZSBzYW1lIGFzIHAxIChpLmUuIG5vIHNtb290aGluZykuXG4gKlxuICogUmV0dXJucyBbbDF4LCBsMXksIHIxeCwgcjF5XVxuICpcbiAqIEl0J3MgZ3VhcmFudGVlZCB0aGF0IHRoZSBsaW5lIGZyb20gKGwxeCwgbDF5KS0ocjF4LCByMXkpIHBhc3NlcyB0aHJvdWdoIHAxLlxuICogVW5sZXNzIGFsbG93RmFsc2VFeHRyZW1hIGlzIHNldCwgdGhlbiBpdCdzIGFsc28gZ3VhcmFudGVlZCB0aGF0OlxuICogICBsMXkg4oiIIFtwMC55LCBwMS55XVxuICogICByMXkg4oiIIFtwMS55LCBwMi55XVxuICpcbiAqIFRoZSBiYXNpYyBhbGdvcml0aG0gaXM6XG4gKiAxLiBQdXQgdGhlIGNvbnRyb2wgcG9pbnRzIGwxIGFuZCByMSDOsSBvZiB0aGUgd2F5IGRvd24gKHAwLCBwMSkgYW5kIChwMSwgcDIpLlxuICogMi4gU2hpZnQgbDEgYW5kIHIyIHNvIHRoYXQgdGhlIGxpbmUgbDHigJNyMSBwYXNzZXMgdGhyb3VnaCBwMVxuICogMy4gQWRqdXN0IHRvIHByZXZlbnQgZmFsc2UgZXh0cmVtYSB3aGlsZSBrZWVwaW5nIHAxIG9uIHRoZSBsMeKAk3IxIGxpbmUuXG4gKlxuICogVGhpcyBpcyBsb29zZWx5IGJhc2VkIG9uIHRoZSBIaWdoQ2hhcnRzIGFsZ29yaXRobS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q29udHJvbFBvaW50cyhwMCwgcDEsIHAyLCBvcHRfYWxwaGEsIG9wdF9hbGxvd0ZhbHNlRXh0cmVtYSkge1xuICB2YXIgYWxwaGEgPSAob3B0X2FscGhhICE9PSB1bmRlZmluZWQpID8gb3B0X2FscGhhIDogMS8zOyAgLy8gMD1ubyBzbW9vdGhpbmcsIDE9Y3Jhenkgc21vb3RoaW5nXG4gIHZhciBhbGxvd0ZhbHNlRXh0cmVtYSA9IG9wdF9hbGxvd0ZhbHNlRXh0cmVtYSB8fCBmYWxzZTtcblxuICBpZiAoIXAyKSB7XG4gICAgcmV0dXJuIFtwMS54LCBwMS55LCBudWxsLCBudWxsXTtcbiAgfVxuXG4gIC8vIFN0ZXAgMTogUG9zaXRpb24gdGhlIGNvbnRyb2wgcG9pbnRzIGFsb25nIGVhY2ggbGluZSBzZWdtZW50LlxuICB2YXIgbDF4ID0gKDEgLSBhbHBoYSkgKiBwMS54ICsgYWxwaGEgKiBwMC54LFxuICAgICAgbDF5ID0gKDEgLSBhbHBoYSkgKiBwMS55ICsgYWxwaGEgKiBwMC55LFxuICAgICAgcjF4ID0gKDEgLSBhbHBoYSkgKiBwMS54ICsgYWxwaGEgKiBwMi54LFxuICAgICAgcjF5ID0gKDEgLSBhbHBoYSkgKiBwMS55ICsgYWxwaGEgKiBwMi55O1xuXG4gIC8vIFN0ZXAgMjogc2hpZnQgdGhlIHBvaW50cyB1cCBzbyB0aGF0IHAxIGlzIG9uIHRoZSBsMeKAk3IxIGxpbmUuXG4gIGlmIChsMXggIT0gcjF4KSB7XG4gICAgLy8gVGhpcyBjYW4gYmUgZGVyaXZlZCB3LyBzb21lIGJhc2ljIGFsZ2VicmEuXG4gICAgdmFyIGRlbHRhWSA9IHAxLnkgLSByMXkgLSAocDEueCAtIHIxeCkgKiAobDF5IC0gcjF5KSAvIChsMXggLSByMXgpO1xuICAgIGwxeSArPSBkZWx0YVk7XG4gICAgcjF5ICs9IGRlbHRhWTtcbiAgfVxuXG4gIC8vIFN0ZXAgMzogY29ycmVjdCB0byBhdm9pZCBmYWxzZSBleHRyZW1hLlxuICBpZiAoIWFsbG93RmFsc2VFeHRyZW1hKSB7XG4gICAgaWYgKGwxeSA+IHAwLnkgJiYgbDF5ID4gcDEueSkge1xuICAgICAgbDF5ID0gTWF0aC5tYXgocDAueSwgcDEueSk7XG4gICAgICByMXkgPSAyICogcDEueSAtIGwxeTtcbiAgICB9IGVsc2UgaWYgKGwxeSA8IHAwLnkgJiYgbDF5IDwgcDEueSkge1xuICAgICAgbDF5ID0gTWF0aC5taW4ocDAueSwgcDEueSk7XG4gICAgICByMXkgPSAyICogcDEueSAtIGwxeTtcbiAgICB9XG5cbiAgICBpZiAocjF5ID4gcDEueSAmJiByMXkgPiBwMi55KSB7XG4gICAgICByMXkgPSBNYXRoLm1heChwMS55LCBwMi55KTtcbiAgICAgIGwxeSA9IDIgKiBwMS55IC0gcjF5O1xuICAgIH0gZWxzZSBpZiAocjF5IDwgcDEueSAmJiByMXkgPCBwMi55KSB7XG4gICAgICByMXkgPSBNYXRoLm1pbihwMS55LCBwMi55KTtcbiAgICAgIGwxeSA9IDIgKiBwMS55IC0gcjF5O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBbbDF4LCBsMXksIHIxeCwgcjF5XTtcbn1cblxuLy8gaS5lLiBpcyBub25lIG9mIChudWxsLCB1bmRlZmluZWQsIE5hTilcbmZ1bmN0aW9uIGlzT0soeCkge1xuICByZXR1cm4gISF4ICYmICFpc05hTih4KTtcbn07XG5cbi8vIEEgcGxvdHRlciB3aGljaCB1c2VzIHNwbGluZXMgdG8gY3JlYXRlIGEgc21vb3RoIGN1cnZlLlxuLy8gU2VlIHRlc3RzL3Bsb3R0ZXJzLmh0bWwgZm9yIGEgZGVtby5cbi8vIENhbiBiZSBjb250cm9sbGVkIHZpYSBzbW9vdGhQbG90dGVyLnNtb290aGluZ1xuZnVuY3Rpb24gc21vb3RoUGxvdHRlcihlKSB7XG4gIHZhciBjdHggPSBlLmRyYXdpbmdDb250ZXh0LFxuICAgICAgcG9pbnRzID0gZS5wb2ludHM7XG5cbiAgY3R4LmJlZ2luUGF0aCgpO1xuICBjdHgubW92ZVRvKHBvaW50c1swXS5jYW52YXN4LCBwb2ludHNbMF0uY2FudmFzeSk7XG5cbiAgLy8gcmlnaHQgY29udHJvbCBwb2ludCBmb3IgcHJldmlvdXMgcG9pbnRcbiAgdmFyIGxhc3RSaWdodFggPSBwb2ludHNbMF0uY2FudmFzeCwgbGFzdFJpZ2h0WSA9IHBvaW50c1swXS5jYW52YXN5O1xuXG4gIGZvciAodmFyIGkgPSAxOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHAwID0gcG9pbnRzW2kgLSAxXSxcbiAgICAgICAgcDEgPSBwb2ludHNbaV0sXG4gICAgICAgIHAyID0gcG9pbnRzW2kgKyAxXTtcbiAgICBwMCA9IHAwICYmIGlzT0socDAuY2FudmFzeSkgPyBwMCA6IG51bGw7XG4gICAgcDEgPSBwMSAmJiBpc09LKHAxLmNhbnZhc3kpID8gcDEgOiBudWxsO1xuICAgIHAyID0gcDIgJiYgaXNPSyhwMi5jYW52YXN5KSA/IHAyIDogbnVsbDtcbiAgICBpZiAocDAgJiYgcDEpIHtcbiAgICAgIHZhciBjb250cm9scyA9IGdldENvbnRyb2xQb2ludHMoe3g6IHAwLmNhbnZhc3gsIHk6IHAwLmNhbnZhc3l9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eDogcDEuY2FudmFzeCwgeTogcDEuY2FudmFzeX0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAyICYmIHt4OiBwMi5jYW52YXN4LCB5OiBwMi5jYW52YXN5fSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoUGxvdHRlci5zbW9vdGhpbmcpO1xuICAgICAgLy8gVW5jb21tZW50IHRvIHNob3cgdGhlIGNvbnRyb2wgcG9pbnRzOlxuICAgICAgLy8gY3R4LmxpbmVUbyhsYXN0UmlnaHRYLCBsYXN0UmlnaHRZKTtcbiAgICAgIC8vIGN0eC5saW5lVG8oY29udHJvbHNbMF0sIGNvbnRyb2xzWzFdKTtcbiAgICAgIC8vIGN0eC5saW5lVG8ocDEuY2FudmFzeCwgcDEuY2FudmFzeSk7XG4gICAgICBsYXN0UmlnaHRYID0gKGxhc3RSaWdodFggIT09IG51bGwpID8gbGFzdFJpZ2h0WCA6IHAwLmNhbnZhc3g7XG4gICAgICBsYXN0UmlnaHRZID0gKGxhc3RSaWdodFkgIT09IG51bGwpID8gbGFzdFJpZ2h0WSA6IHAwLmNhbnZhc3k7XG4gICAgICBjdHguYmV6aWVyQ3VydmVUbyhsYXN0UmlnaHRYLCBsYXN0UmlnaHRZLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbHNbMF0sIGNvbnRyb2xzWzFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgcDEuY2FudmFzeCwgcDEuY2FudmFzeSk7XG4gICAgICBsYXN0UmlnaHRYID0gY29udHJvbHNbMl07XG4gICAgICBsYXN0UmlnaHRZID0gY29udHJvbHNbM107XG4gICAgfSBlbHNlIGlmIChwMSkge1xuICAgICAgLy8gV2UncmUgc3RhcnRpbmcgYWdhaW4gYWZ0ZXIgYSBtaXNzaW5nIHBvaW50LlxuICAgICAgY3R4Lm1vdmVUbyhwMS5jYW52YXN4LCBwMS5jYW52YXN5KTtcbiAgICAgIGxhc3RSaWdodFggPSBwMS5jYW52YXN4O1xuICAgICAgbGFzdFJpZ2h0WSA9IHAxLmNhbnZhc3k7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxhc3RSaWdodFggPSBsYXN0UmlnaHRZID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBjdHguc3Ryb2tlKCk7XG59XG5zbW9vdGhQbG90dGVyLnNtb290aGluZyA9IDEvMztcbnNtb290aFBsb3R0ZXIuX2dldENvbnRyb2xQb2ludHMgPSBnZXRDb250cm9sUG9pbnRzOyAgLy8gZm9yIHRlc3RpbmdcblxuLy8gb2xkZXIgdmVyc2lvbnMgZXhwb3J0ZWQgYSBnbG9iYWwuXG4vLyBUaGlzIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgZnV0dXJlLlxuLy8gVGhlIHByZWZlcnJlZCB3YXkgdG8gYWNjZXNzIHNtb290aFBsb3R0ZXIgaXMgdmlhIER5Z3JhcGguc21vb3RoUGxvdHRlci5cbndpbmRvdy5zbW9vdGhQbG90dGVyID0gc21vb3RoUGxvdHRlcjtcbkR5Z3JhcGguc21vb3RoUGxvdHRlciA9IHNtb290aFBsb3R0ZXI7XG5cbi8qIGNsb3N1cmUgYW5kIGxvYWRlciB3cmFwcGVyICovXG5EeWdyYXBoLl9yZXF1aXJlLmFkZCgnZHlncmFwaHMvc3JjL2V4dHJhcy9zbW9vdGgtcGxvdHRlci5qcycsIC8qIGV4cG9ydHMgKi8ge30pO1xufSkoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQyxTQUFTQSw2QkFBNkJBLENBQUEsRUFBRztFQUMxQyxZQUFZOztFQUNaLElBQUlDLE9BQU87RUFDWCxJQUFJQyxNQUFNLENBQUNELE9BQU8sRUFBRTtJQUNsQkEsT0FBTyxHQUFHQyxNQUFNLENBQUNELE9BQU87RUFDMUIsQ0FBQyxNQUFNLElBQUksT0FBT0UsTUFBTyxLQUFLLFdBQVcsRUFBRTtJQUN6Q0YsT0FBTyxHQUFHRyxPQUFPLENBQUMsWUFBWSxDQUFDO0lBQy9CLElBQUksT0FBT0gsT0FBTyxDQUFDSSxJQUFLLEtBQUssV0FBVyxJQUFJLE9BQU9KLE9BQU8sV0FBUyxLQUFLLFdBQVcsRUFDakZBLE9BQU8sR0FBR0EsT0FBTyxXQUFRO0VBQzdCO0VBQ0E7O0VBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNBLFNBQVNLLGdCQUFnQkEsQ0FBQ0MsRUFBRSxFQUFFQyxFQUFFLEVBQUVDLEVBQUUsRUFBRUMsU0FB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