UNPKG

dygraphs

Version:

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

154 lines (142 loc) 19.1 kB
"use strict"; /** * @license * Part of dygraphs, see top-level LICENSE.txt file * MIT-licenced: https://opensource.org/licenses/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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXh0cmFzX3Ntb290aFBsb3R0ZXJfY2xvc3VyZSIsIkR5Z3JhcGgiLCJ3aW5kb3ciLCJtb2R1bGUiLCJyZXF1aXJlIiwiTkFNRSIsImdldENvbnRyb2xQb2ludHMiLCJwMCIsInAxIiwicDIiLCJvcHRfYWxwaGEiLCJvcHRfYWxsb3dGYWxzZUV4dHJlbWEiLCJhbHBoYSIsInVuZGVmaW5lZCIsImFsbG93RmFsc2VFeHRyZW1hIiwieCIsInkiLCJsMXgiLCJsMXkiLCJyMXgiLCJyMXkiLCJkZWx0YVkiLCJNYXRoIiwibWF4IiwibWluIiwiaXNPSyIsImlzTmFOIiwic21vb3RoUGxvdHRlciIsImUiLCJjdHgiLCJkcmF3aW5nQ29udGV4dCIsInBvaW50cyIsImJlZ2luUGF0aCIsIm1vdmVUbyIsImNhbnZhc3giLCJjYW52YXN5IiwibGFzdFJpZ2h0WCIsImxhc3RSaWdodFkiLCJpIiwibGVuZ3RoIiwiY29udHJvbHMiLCJzbW9vdGhpbmciLCJiZXppZXJDdXJ2ZVRvIiwic3Ryb2tlIiwiX2dldENvbnRyb2xQb2ludHMiLCJfcmVxdWlyZSIsImFkZCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHRyYXMvc21vb3RoLXBsb3R0ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogUGFydCBvZiBkeWdyYXBocywgc2VlIHRvcC1sZXZlbCBMSUNFTlNFLnR4dCBmaWxlXG4gKiBNSVQtbGljZW5jZWQ6IGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlUXG4gKi9cblxuLyogbG9hZGVyIHdyYXBwZXIgdG8gYWxsb3cgYnJvd3NlciB1c2UgYW5kIEVTNiBpbXBvcnRzICovXG4oZnVuY3Rpb24gX2V4dHJhc19zbW9vdGhQbG90dGVyX2Nsb3N1cmUoKSB7XG4ndXNlIHN0cmljdCc7XG52YXIgRHlncmFwaDtcbmlmICh3aW5kb3cuRHlncmFwaCkge1xuICBEeWdyYXBoID0gd2luZG93LkR5Z3JhcGg7XG59IGVsc2UgaWYgKHR5cGVvZihtb2R1bGUpICE9PSAndW5kZWZpbmVkJykge1xuICBEeWdyYXBoID0gcmVxdWlyZSgnLi4vZHlncmFwaCcpO1xuICBpZiAodHlwZW9mKER5Z3JhcGguTkFNRSkgPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZihEeWdyYXBoLmRlZmF1bHQpICE9PSAndW5kZWZpbmVkJylcbiAgICBEeWdyYXBoID0gRHlncmFwaC5kZWZhdWx0O1xufVxuLyogZW5kIG9mIGxvYWRlciB3cmFwcGVyIGhlYWRlciAqL1xuXG4vKipcbiAqIEdpdmVuIHRocmVlIHNlcXVlbnRpYWwgcG9pbnRzLCBwMCwgcDEgYW5kIHAyLCBmaW5kIHRoZSBsZWZ0IGFuZCByaWdodFxuICogY29udHJvbCBwb2ludHMgZm9yIHAxLlxuICpcbiAqIFRoZSB0aHJlZSBwb2ludHMgYXJlIGV4cGVjdGVkIHRvIGhhdmUgeCBhbmQgeSBwcm9wZXJ0aWVzLlxuICpcbiAqIFRoZSBhbHBoYSBwYXJhbWV0ZXIgY29udHJvbHMgdGhlIGFtb3VudCBvZiBzbW9vdGhpbmcuXG4gKiBJZiDOsT0wLCB0aGVuIGJvdGggY29udHJvbCBwb2ludHMgd2lsbCBiZSB0aGUgc2FtZSBhcyBwMSAoaS5lLiBubyBzbW9vdGhpbmcpLlxuICpcbiAqIFJldHVybnMgW2wxeCwgbDF5LCByMXgsIHIxeV1cbiAqXG4gKiBJdCdzIGd1YXJhbnRlZWQgdGhhdCB0aGUgbGluZSBmcm9tIChsMXgsIGwxeSktKHIxeCwgcjF5KSBwYXNzZXMgdGhyb3VnaCBwMS5cbiAqIFVubGVzcyBhbGxvd0ZhbHNlRXh0cmVtYSBpcyBzZXQsIHRoZW4gaXQncyBhbHNvIGd1YXJhbnRlZWQgdGhhdDpcbiAqICAgbDF5IOKIiCBbcDAueSwgcDEueV1cbiAqICAgcjF5IOKIiCBbcDEueSwgcDIueV1cbiAqXG4gKiBUaGUgYmFzaWMgYWxnb3JpdGhtIGlzOlxuICogMS4gUHV0IHRoZSBjb250cm9sIHBvaW50cyBsMSBhbmQgcjEgzrEgb2YgdGhlIHdheSBkb3duIChwMCwgcDEpIGFuZCAocDEsIHAyKS5cbiAqIDIuIFNoaWZ0IGwxIGFuZCByMiBzbyB0aGF0IHRoZSBsaW5lIGwx4oCTcjEgcGFzc2VzIHRocm91Z2ggcDFcbiAqIDMuIEFkanVzdCB0byBwcmV2ZW50IGZhbHNlIGV4dHJlbWEgd2hpbGUga2VlcGluZyBwMSBvbiB0aGUgbDHigJNyMSBsaW5lLlxuICpcbiAqIFRoaXMgaXMgbG9vc2VseSBiYXNlZCBvbiB0aGUgSGlnaENoYXJ0cyBhbGdvcml0aG0uXG4gKi9cbmZ1bmN0aW9uIGdldENvbnRyb2xQb2ludHMocDAsIHAxLCBwMiwgb3B0X2FscGhhLCBvcHRfYWxsb3dGYWxzZUV4dHJlbWEpIHtcbiAgdmFyIGFscGhhID0gKG9wdF9hbHBoYSAhPT0gdW5kZWZpbmVkKSA/IG9wdF9hbHBoYSA6IDEvMzsgIC8vIDA9bm8gc21vb3RoaW5nLCAxPWNyYXp5IHNtb290aGluZ1xuICB2YXIgYWxsb3dGYWxzZUV4dHJlbWEgPSBvcHRfYWxsb3dGYWxzZUV4dHJlbWEgfHwgZmFsc2U7XG5cbiAgaWYgKCFwMikge1xuICAgIHJldHVybiBbcDEueCwgcDEueSwgbnVsbCwgbnVsbF07XG4gIH1cblxuICAvLyBTdGVwIDE6IFBvc2l0aW9uIHRoZSBjb250cm9sIHBvaW50cyBhbG9uZyBlYWNoIGxpbmUgc2VnbWVudC5cbiAgdmFyIGwxeCA9ICgxIC0gYWxwaGEpICogcDEueCArIGFscGhhICogcDAueCxcbiAgICAgIGwxeSA9ICgxIC0gYWxwaGEpICogcDEueSArIGFscGhhICogcDAueSxcbiAgICAgIHIxeCA9ICgxIC0gYWxwaGEpICogcDEueCArIGFscGhhICogcDIueCxcbiAgICAgIHIxeSA9ICgxIC0gYWxwaGEpICogcDEueSArIGFscGhhICogcDIueTtcblxuICAvLyBTdGVwIDI6IHNoaWZ0IHRoZSBwb2ludHMgdXAgc28gdGhhdCBwMSBpcyBvbiB0aGUgbDHigJNyMSBsaW5lLlxuICBpZiAobDF4ICE9IHIxeCkge1xuICAgIC8vIFRoaXMgY2FuIGJlIGRlcml2ZWQgdy8gc29tZSBiYXNpYyBhbGdlYnJhLlxuICAgIHZhciBkZWx0YVkgPSBwMS55IC0gcjF5IC0gKHAxLnggLSByMXgpICogKGwxeSAtIHIxeSkgLyAobDF4IC0gcjF4KTtcbiAgICBsMXkgKz0gZGVsdGFZO1xuICAgIHIxeSArPSBkZWx0YVk7XG4gIH1cblxuICAvLyBTdGVwIDM6IGNvcnJlY3QgdG8gYXZvaWQgZmFsc2UgZXh0cmVtYS5cbiAgaWYgKCFhbGxvd0ZhbHNlRXh0cmVtYSkge1xuICAgIGlmIChsMXkgPiBwMC55ICYmIGwxeSA+IHAxLnkpIHtcbiAgICAgIGwxeSA9IE1hdGgubWF4KHAwLnksIHAxLnkpO1xuICAgICAgcjF5ID0gMiAqIHAxLnkgLSBsMXk7XG4gICAgfSBlbHNlIGlmIChsMXkgPCBwMC55ICYmIGwxeSA8IHAxLnkpIHtcbiAgICAgIGwxeSA9IE1hdGgubWluKHAwLnksIHAxLnkpO1xuICAgICAgcjF5ID0gMiAqIHAxLnkgLSBsMXk7XG4gICAgfVxuXG4gICAgaWYgKHIxeSA+IHAxLnkgJiYgcjF5ID4gcDIueSkge1xuICAgICAgcjF5ID0gTWF0aC5tYXgocDEueSwgcDIueSk7XG4gICAgICBsMXkgPSAyICogcDEueSAtIHIxeTtcbiAgICB9IGVsc2UgaWYgKHIxeSA8IHAxLnkgJiYgcjF5IDwgcDIueSkge1xuICAgICAgcjF5ID0gTWF0aC5taW4ocDEueSwgcDIueSk7XG4gICAgICBsMXkgPSAyICogcDEueSAtIHIxeTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gW2wxeCwgbDF5LCByMXgsIHIxeV07XG59XG5cbi8vIGkuZS4gaXMgbm9uZSBvZiAobnVsbCwgdW5kZWZpbmVkLCBOYU4pXG5mdW5jdGlvbiBpc09LKHgpIHtcbiAgcmV0dXJuICEheCAmJiAhaXNOYU4oeCk7XG59O1xuXG4vLyBBIHBsb3R0ZXIgd2hpY2ggdXNlcyBzcGxpbmVzIHRvIGNyZWF0ZSBhIHNtb290aCBjdXJ2ZS5cbi8vIFNlZSB0ZXN0cy9wbG90dGVycy5odG1sIGZvciBhIGRlbW8uXG4vLyBDYW4gYmUgY29udHJvbGxlZCB2aWEgc21vb3RoUGxvdHRlci5zbW9vdGhpbmdcbmZ1bmN0aW9uIHNtb290aFBsb3R0ZXIoZSkge1xuICB2YXIgY3R4ID0gZS5kcmF3aW5nQ29udGV4dCxcbiAgICAgIHBvaW50cyA9IGUucG9pbnRzO1xuXG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgY3R4Lm1vdmVUbyhwb2ludHNbMF0uY2FudmFzeCwgcG9pbnRzWzBdLmNhbnZhc3kpO1xuXG4gIC8vIHJpZ2h0IGNvbnRyb2wgcG9pbnQgZm9yIHByZXZpb3VzIHBvaW50XG4gIHZhciBsYXN0UmlnaHRYID0gcG9pbnRzWzBdLmNhbnZhc3gsIGxhc3RSaWdodFkgPSBwb2ludHNbMF0uY2FudmFzeTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwMCA9IHBvaW50c1tpIC0gMV0sXG4gICAgICAgIHAxID0gcG9pbnRzW2ldLFxuICAgICAgICBwMiA9IHBvaW50c1tpICsgMV07XG4gICAgcDAgPSBwMCAmJiBpc09LKHAwLmNhbnZhc3kpID8gcDAgOiBudWxsO1xuICAgIHAxID0gcDEgJiYgaXNPSyhwMS5jYW52YXN5KSA/IHAxIDogbnVsbDtcbiAgICBwMiA9IHAyICYmIGlzT0socDIuY2FudmFzeSkgPyBwMiA6IG51bGw7XG4gICAgaWYgKHAwICYmIHAxKSB7XG4gICAgICB2YXIgY29udHJvbHMgPSBnZXRDb250cm9sUG9pbnRzKHt4OiBwMC5jYW52YXN4LCB5OiBwMC5jYW52YXN5fSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3g6IHAxLmNhbnZhc3gsIHk6IHAxLmNhbnZhc3l9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwMiAmJiB7eDogcDIuY2FudmFzeCwgeTogcDIuY2FudmFzeX0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNtb290aFBsb3R0ZXIuc21vb3RoaW5nKTtcbiAgICAgIC8vIFVuY29tbWVudCB0byBzaG93IHRoZSBjb250cm9sIHBvaW50czpcbiAgICAgIC8vIGN0eC5saW5lVG8obGFzdFJpZ2h0WCwgbGFzdFJpZ2h0WSk7XG4gICAgICAvLyBjdHgubGluZVRvKGNvbnRyb2xzWzBdLCBjb250cm9sc1sxXSk7XG4gICAgICAvLyBjdHgubGluZVRvKHAxLmNhbnZhc3gsIHAxLmNhbnZhc3kpO1xuICAgICAgbGFzdFJpZ2h0WCA9IChsYXN0UmlnaHRYICE9PSBudWxsKSA/IGxhc3RSaWdodFggOiBwMC5jYW52YXN4O1xuICAgICAgbGFzdFJpZ2h0WSA9IChsYXN0UmlnaHRZICE9PSBudWxsKSA/IGxhc3RSaWdodFkgOiBwMC5jYW52YXN5O1xuICAgICAgY3R4LmJlemllckN1cnZlVG8obGFzdFJpZ2h0WCwgbGFzdFJpZ2h0WSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzWzBdLCBjb250cm9sc1sxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHAxLmNhbnZhc3gsIHAxLmNhbnZhc3kpO1xuICAgICAgbGFzdFJpZ2h0WCA9IGNvbnRyb2xzWzJdO1xuICAgICAgbGFzdFJpZ2h0WSA9IGNvbnRyb2xzWzNdO1xuICAgIH0gZWxzZSBpZiAocDEpIHtcbiAgICAgIC8vIFdlJ3JlIHN0YXJ0aW5nIGFnYWluIGFmdGVyIGEgbWlzc2luZyBwb2ludC5cbiAgICAgIGN0eC5tb3ZlVG8ocDEuY2FudmFzeCwgcDEuY2FudmFzeSk7XG4gICAgICBsYXN0UmlnaHRYID0gcDEuY2FudmFzeDtcbiAgICAgIGxhc3RSaWdodFkgPSBwMS5jYW52YXN5O1xuICAgIH0gZWxzZSB7XG4gICAgICBsYXN0UmlnaHRYID0gbGFzdFJpZ2h0WSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgY3R4LnN0cm9rZSgpO1xufVxuc21vb3RoUGxvdHRlci5zbW9vdGhpbmcgPSAxLzM7XG5zbW9vdGhQbG90dGVyLl9nZXRDb250cm9sUG9pbnRzID0gZ2V0Q29udHJvbFBvaW50czsgIC8vIGZvciB0ZXN0aW5nXG5cbi8vIG9sZGVyIHZlcnNpb25zIGV4cG9ydGVkIGEgZ2xvYmFsLlxuLy8gVGhpcyB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIGZ1dHVyZS5cbi8vIFRoZSBwcmVmZXJyZWQgd2F5IHRvIGFjY2VzcyBzbW9vdGhQbG90dGVyIGlzIHZpYSBEeWdyYXBoLnNtb290aFBsb3R0ZXIuXG53aW5kb3cuc21vb3RoUGxvdHRlciA9IHNtb290aFBsb3R0ZXI7XG5EeWdyYXBoLnNtb290aFBsb3R0ZXIgPSBzbW9vdGhQbG90dGVyO1xuXG4vKiBjbG9zdXJlIGFuZCBsb2FkZXIgd3JhcHBlciAqL1xuRHlncmFwaC5fcmVxdWlyZS5hZGQoJ2R5Z3JhcGhzL3NyYy9leHRyYXMvc21vb3RoLXBsb3R0ZXIuanMnLCAvKiBleHBvcnRzICovIHt9KTtcbn0pKCk7XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUMsU0FBU0EsNkJBQTZCLEdBQUc7RUFDMUMsWUFBWTs7RUFDWixJQUFJQyxPQUFPO0VBQ1gsSUFBSUMsTUFBTSxDQUFDRCxPQUFPLEVBQUU7SUFDbEJBLE9BQU8sR0FBR0MsTUFBTSxDQUFDRCxPQUFPO0VBQzFCLENBQUMsTUFBTSxJQUFJLE9BQU9FLE1BQU8sS0FBSyxXQUFXLEVBQUU7SUFDekNGLE9BQU8sR0FBR0csT0FBTyxDQUFDLFlBQVksQ0FBQztJQUMvQixJQUFJLE9BQU9ILE9BQU8sQ0FBQ0ksSUFBSyxLQUFLLFdBQVcsSUFBSSxPQUFPSixPQUFPLFdBQVMsS0FBSyxXQUFXLEVBQ2pGQSxPQUFPLEdBQUdBLE9BQU8sV0FBUTtFQUM3QjtFQUNBOztFQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDQSxTQUFTSyxnQkFBZ0IsQ0FBQ0MsRUFBRSxFQUFFQyxFQUFFLEVBQUVDLEVBQUUsRUFBRUMsU0FBUyxFQUFF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