UNPKG

43.3 kBJavaScriptView Raw
1"use strict";
2/*
3 * I need to do the following:
4 * diff angles between vectors
5 * find perpendicular vector to a point on a path
6 * find tangent to a point on a path
7 * transform (translate, rotate) for nodes and edges
8 * es modules so I can pull out just what I need
9 *
10 * Specs to compare:
11 * tests
12 * typescript
13 * maintained (open issues unresolved for a long time?)
14 * node and browser
15*/
16Object.defineProperty(exports, "__esModule", { value: true });
17var lodash_1 = require("lodash");
18var fp_1 = require("lodash/fp");
19var Angle_1 = require("./spinoffs/Angle");
20var points_1 = require("points");
21// TODO why doesn't the following work?
22// Also, why doesn't ../node_modules/kaavio/lib/drawers/edges/ exist?
23//import * as edgeDrawers from "kaavio/src/drawers/edges/index";
24//import * as edgeDrawers from "../node_modules/kaavio/src/drawers/edges/index";
25//import * as edgeDrawers from "kaavio/src/drawers/edges/index";
26//import * as edgeDrawers from "kaavio/lib/drawers/edges/index";
27var edgeDrawers = require("./edge/edgeDrawers");
28// We are using the standard SVG coordinate system where:
29// the origin is the upper-left-most point
30// positive x is to the right
31// positive y is down
32// uses left hand rule, so positive angle is clockwise,
33// starting with 0 pointing to the right
34// The orientation is a unit vector that indicates the orientation of an
35// at a point. When it is attached to a rectangle, we almost always want it to
36// point away from the side to which it is attached.
37exports.START_SIDE_TO_ORIENTATION_MAP = {
38 right: [1, 0],
39 bottom: [0, 1],
40 left: [-1, 0],
41 top: [0, -1]
42};
43exports.START_SIDE_TO_EMANATION_ANGLE_MAPPINGS = fp_1.fromPairs(fp_1.toPairs(exports.START_SIDE_TO_ORIENTATION_MAP).map(function (_a) {
44 var startSide = _a[0], orientation = _a[1];
45 return [startSide, Angle_1.fromSlope([0, 0], orientation)];
46}));
47exports.EMANATION_ANGLE_TO_START_SIDE_MAPPINGS = fp_1.toPairs(exports.START_SIDE_TO_EMANATION_ANGLE_MAPPINGS).reduce(function (acc, _a) {
48 var side = _a[0], angle = _a[1];
49 acc.set(angle, side);
50 return acc;
51}, new Map());
52exports.START_SEGMENT_DETAILS_MAPS = fp_1.toPairs(exports.START_SIDE_TO_ORIENTATION_MAP).map(function (_a) {
53 var startSide = _a[0], orientation = _a[1];
54 var orientationX = orientation[0], orientationY = orientation[1];
55 return {
56 sideAttachedTo: startSide,
57 orientation: orientation,
58 angle: Angle_1.normalize(Math.atan2(orientationY, orientationX))
59 };
60});
61var SmartPoint = /** @class */ (function () {
62 //orientationVector?: SmartVector;
63 function SmartPoint(point) {
64 var _this = this;
65 this.angle = function () {
66 return Angle_1.fromSlope([0, 0], _this.orientation);
67 };
68 this.fromArray = function (_a) {
69 var x = _a[0], y = _a[1];
70 _this.x = x;
71 _this.y = y;
72 };
73 this.toArray = function () {
74 return [_this.x, _this.y];
75 };
76 lodash_1.assign(this, point);
77 /*
78 if (!isUndefined(this.orientation)) {
79 this.orientationVector = new SmartVector(
80 { x: 0, y: 0 },
81 { x: this.orientation[0], y: this.orientation[1] }
82 );
83 }
84 //*/
85 }
86 return SmartPoint;
87}());
88exports.SmartPoint = SmartPoint;
89var SmartVector = /** @class */ (function () {
90 function SmartVector(p0, p1) {
91 var _this = this;
92 this.angleDistance = function (vector2) {
93 return Angle_1.distance(_this.angle, vector2.angle);
94 };
95 this.p0 = new SmartPoint(p0);
96 this.p1 = new SmartPoint(p1);
97 this.angle = Angle_1.fromSlope(this.p0.toArray(), this.p1.toArray());
98 }
99 return SmartVector;
100}());
101exports.SmartVector = SmartVector;
102var SmartPath = /** @class */ (function () {
103 function SmartPath(points, edge) {
104 var _this = this;
105 this.position = function (scalar, accuracy) {
106 var _a = points_1.position(_this.path.points, scalar, accuracy), x = _a.x, y = _a.y, degreesFromNorth = _a.angle;
107 /* the points library returns the angle from north, in degrees, increasing CW, so
108 * this has an angle of 0 deg.:
109 *
110 * ^
111 * |
112 * |
113 * |
114 *
115 * and this has an angle of 90 deg.:
116 *
117 * ------->
118 */
119 return {
120 x: x,
121 y: y,
122 // convert to radians and use angle orientation of SVG coordinate system
123 angle: Angle_1.normalize(Angle_1.degreesToRadians(degreesFromNorth + 270))
124 };
125 };
126 var smartPoints = points.map(function (point) { return new SmartPoint(point); });
127 this.points = smartPoints;
128 this.sum = new SmartVector(smartPoints[0], fp_1.last(smartPoints));
129 if (!fp_1.isUndefined(edge)) {
130 var points_2 = edge.points, markerStart = edge.markerStart, markerEnd = edge.markerEnd;
131 this.path = new edgeDrawers[edge.drawAs](smartPoints, markerStart, markerEnd);
132 }
133 }
134 return SmartPath;
135}());
136exports.SmartPath = SmartPath;
137// TODO explore using the packages points and angles (and maybe vectory) together
138var smartPath1 = new SmartPath([
139 { x: 50, y: 30, moveTo: true },
140 { x: 50, y: 70, curve: { type: "arc", rx: 20, ry: 20, sweepFlag: 1 } },
141 { x: 150, y: 100, curve: { type: "arc", rx: 20, ry: 20, sweepFlag: 1 } }
142]);
143var smartPath2 = new SmartPath([
144 { x: 100, y: 50, moveTo: true },
145 { x: 50, y: 70, curve: { type: "arc", rx: 20, ry: 20, sweepFlag: 1 } }
146 //{ x: 200, y: 100 }
147]);
148/* OLD CODE BELOW */
149function addAngles(angle1, angle2) {
150 var sum = angle1 + angle2;
151 var singleRevolutionSum = sum % (2 * Math.PI);
152 return Math.sign(singleRevolutionSum) === -1
153 ? 2 * Math.PI + singleRevolutionSum
154 : singleRevolutionSum;
155}
156exports.addAngles = addAngles;
157// see https://gist.github.com/ahwolf/4349166 and
158// http://www.blackpawn.com/texts/pointinpoly/default.html
159function crossProduct(u, v) {
160 return u[0] * v[1] - v[0] * u[1];
161}
162exports.crossProduct = crossProduct;
163function flipOrientation(orientation) {
164 return orientation.map(function (orientationScalar) { return -1 * orientationScalar; });
165}
166exports.flipOrientation = flipOrientation;
167function flipSide(side) {
168 return exports.EMANATION_ANGLE_TO_START_SIDE_MAPPINGS.get(reverseAngle(exports.START_SIDE_TO_EMANATION_ANGLE_MAPPINGS[side]));
169}
170exports.flipSide = flipSide;
171function getMinimumAngleBetweenVectors(vectorDirectionAngle1, vectorDirectionAngle2) {
172 var vectors = [vectorDirectionAngle1, vectorDirectionAngle2];
173 var minVector = Math.min.apply(undefined, vectors);
174 var maxVector = Math.max.apply(undefined, vectors);
175 if (minVector < 0 || maxVector >= 2 * Math.PI) {
176 throw new Error("getMinimumAngleBetweenVectors(" + vectorDirectionAngle1 + ", " + vectorDirectionAngle2 + ")\n\t\t\t\t\t\t\t\t\t\tinputs must be in interval [0, 2 * Math.PI).");
177 }
178 return (Math.max(vectorDirectionAngle1, vectorDirectionAngle2) -
179 Math.min(vectorDirectionAngle1, vectorDirectionAngle2));
180 /*
181 const diff = addAngles(vectorDirectionAngle1, -1 * vectorDirectionAngle2);
182 return diff <= Math.PI ? diff : diff % Math.PI;
183 //*/
184 //return diff > Math.PI ? diff - Math.PI : diff;
185}
186exports.getMinimumAngleBetweenVectors = getMinimumAngleBetweenVectors;
187function getAngleOfEmanationFromPoint(point) {
188 var _a = point.orientation, orientationX = _a[0], orientationY = _a[1];
189 return Math.atan2(orientationY, orientationX);
190}
191exports.getAngleOfEmanationFromPoint = getAngleOfEmanationFromPoint;
192function reverseAngle(angle) {
193 return addAngles(angle, Math.PI);
194}
195exports.reverseAngle = reverseAngle;
196function getAngleAtPoint(edge, positionX) {
197 var id = edge.id, points = edge.points, markerStart = edge.markerStart, markerEnd = edge.markerEnd;
198 var referencedPath = new edgeDrawers[(edge.drawAs.toLowerCase())](points, markerStart, markerEnd);
199 var tangentLength = 0.02;
200 var firstPointOfTangent = referencedPath.getPointAtPosition(Math.max(0, positionX - tangentLength / 2));
201 var lastPointOfTangent = referencedPath.getPointAtPosition(Math.min(1, positionX + tangentLength / 2));
202 return getAngleFromPointToPoint(firstPointOfTangent, lastPointOfTangent);
203}
204exports.getAngleAtPoint = getAngleAtPoint;
205function getAngleFromPointToPoint(_a, _b) {
206 var x0 = _a.x, y0 = _a.y;
207 var x1 = _b.x, y1 = _b.y;
208 return Math.atan2(y1 - y0, x1 - x0);
209}
210exports.getAngleFromPointToPoint = getAngleFromPointToPoint;
211function getStartSideByOrientation(_a) {
212 var orientationX = _a[0], orientationY = _a[1];
213 if (Math.abs(orientationX) > Math.abs(orientationY)) {
214 if (orientationX > 0) {
215 return "right"; //East
216 }
217 else {
218 return "left"; //West
219 }
220 }
221 else {
222 if (orientationY > 0) {
223 return "bottom"; //South
224 }
225 else {
226 return "top"; //North
227 }
228 }
229}
230exports.getStartSideByOrientation = getStartSideByOrientation;
231// see http://blog.acipo.com/matrix-inversion-in-javascript/
232/**
233 * Calculate the inverse matrix.
234 * @returns {Matrix}
235 */
236function invertMatrix(M) {
237 // I use Guassian Elimination to calculate the inverse:
238 // (1) 'augment' the matrix (left) by the identity (on the right)
239 // (2) Turn the matrix on the left into the identity by elemetry row ops
240 // (3) The matrix on the right is the inverse (was the identity matrix)
241 // There are 3 elemtary row ops: (I combine b and c in my code)
242 // (a) Swap 2 rows
243 // (b) Multiply a row by a scalar
244 // (c) Add 2 rows
245 //if the matrix isn't square: exit (error)
246 if (M.length !== M[0].length) {
247 return;
248 }
249 //create the identity matrix (I), and a copy (C) of the original
250 var i = 0, ii = 0, j = 0, dim = M.length, e = 0, t = 0;
251 var I = [], C = [];
252 for (i = 0; i < dim; i += 1) {
253 // Create the row
254 I[I.length] = [];
255 C[C.length] = [];
256 for (j = 0; j < dim; j += 1) {
257 //if we're on the diagonal, put a 1 (for identity)
258 if (i === j) {
259 I[i][j] = 1;
260 }
261 else {
262 I[i][j] = 0;
263 }
264 // Also, make the copy of the original
265 C[i][j] = M[i][j];
266 }
267 }
268 // Perform elementary row operations
269 for (i = 0; i < dim; i += 1) {
270 // get the element e on the diagonal
271 e = C[i][i];
272 // if we have a 0 on the diagonal (we'll need to swap with a lower row)
273 if (e === 0) {
274 //look through every row below the i'th row
275 for (ii = i + 1; ii < dim; ii += 1) {
276 //if the ii'th row has a non-0 in the i'th col
277 if (C[ii][i] !== 0) {
278 //it would make the diagonal have a non-0 so swap it
279 for (j = 0; j < dim; j++) {
280 e = C[i][j]; //temp store i'th row
281 C[i][j] = C[ii][j]; //replace i'th row by ii'th
282 C[ii][j] = e; //repace ii'th by temp
283 e = I[i][j]; //temp store i'th row
284 I[i][j] = I[ii][j]; //replace i'th row by ii'th
285 I[ii][j] = e; //repace ii'th by temp
286 }
287 //don't bother checking other rows since we've swapped
288 break;
289 }
290 }
291 //get the new diagonal
292 e = C[i][i];
293 //if it's still 0, not invertable (error)
294 if (e === 0) {
295 return;
296 }
297 }
298 // Scale this row down by e (so we have a 1 on the diagonal)
299 for (j = 0; j < dim; j++) {
300 C[i][j] = C[i][j] / e; //apply to original matrix
301 I[i][j] = I[i][j] / e; //apply to identity
302 }
303 // Subtract this row (scaled appropriately for each row) from ALL of
304 // the other rows so that there will be 0's in this column in the
305 // rows above and below this one
306 for (ii = 0; ii < dim; ii++) {
307 // Only apply to other rows (we want a 1 on the diagonal)
308 if (ii === i) {
309 continue;
310 }
311 // We want to change this element to 0
312 e = C[ii][i];
313 // Subtract (the row above(or below) scaled by e) from (the
314 // current row) but start at the i'th column and assume all the
315 // stuff left of diagonal is 0 (which it should be if we made this
316 // algorithm correctly)
317 for (j = 0; j < dim; j++) {
318 C[ii][j] -= e * C[i][j]; //apply to original matrix
319 I[ii][j] -= e * I[i][j]; //apply to identity
320 }
321 }
322 }
323 //we've done all operations, C should be the identity
324 //matrix I should be the inverse:
325 return I;
326}
327exports.invertMatrix = invertMatrix;
328// from http://tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascript
329function multiplyMatrices(m1, m2) {
330 var result = [];
331 for (var i = 0; i < m1.length; i++) {
332 result[i] = [];
333 for (var j = 0; j < m2[0].length; j++) {
334 var sum = 0;
335 for (var k = 0; k < m1[0].length; k++) {
336 sum += m1[i][k] * m2[k][j];
337 }
338 result[i][j] = sum;
339 }
340 }
341 return result;
342}
343exports.multiplyMatrices = multiplyMatrices;
344/**
345 * rotate
346 *
347 * @param theta (float): rotation angle in radians, measured clockwise
348 * @return transformation matrix for rotation
349 *
350 * Note that for Canvas and SVG, the y axis points down:
351 *
352 * *---------> x
353 * |
354 * |
355 * |
356 * v
357 *
358 * y
359 *
360 * The transformation matrix returned takes this into account and is intentionally
361 * different from the transformation matrix that would be returned if the y-axis
362 * pointed up, as is common in many math classes.
363 */
364function rotate(theta) {
365 if (!fp_1.isFinite(theta)) {
366 throw new Error("Invalid input: rotate(" + theta + "). Requires a finite number.");
367 }
368 return [
369 [Math.cos(theta), -1 * Math.sin(theta), 0],
370 [Math.sin(theta), Math.cos(theta), 0],
371 [0, 0, 1]
372 ];
373}
374exports.rotate = rotate;
375function scale(_a) {
376 var xScale = _a[0], yScale = _a[1];
377 if (!fp_1.isFinite(xScale) || !fp_1.isFinite(yScale)) {
378 throw new Error("Invalid input: rotate([" + xScale + ", " + yScale + "]). Requires array of two finite numbers.");
379 }
380 return [[xScale, 0, 0], [0, yScale, 0], [0, 0, 1]];
381}
382exports.scale = scale;
383function translate(_a) {
384 var xTranslation = _a[0], yTranslation = _a[1];
385 if (!fp_1.isFinite(xTranslation) || !fp_1.isFinite(yTranslation)) {
386 throw new Error("Invalid input: translate([" + xTranslation + ", " + yTranslation + "]). Requires array of two finite numbers.");
387 }
388 return [[1, 0, xTranslation], [0, 1, yTranslation], [0, 0, 1]];
389}
390exports.translate = translate;
391var transformations = {
392 rotate: rotate,
393 scale: scale,
394 translate: translate
395};
396function getTransformationMatrix(transformationSequence) {
397 // Start with identity matrix
398 var concatenatedTransformationMatrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
399 transformationSequence.forEach(function (transformation) {
400 var thisTransformationMatrix = transformations[transformation.key](transformation.value);
401 concatenatedTransformationMatrix = multiplyMatrices(concatenatedTransformationMatrix, thisTransformationMatrix);
402 });
403 return concatenatedTransformationMatrix;
404}
405exports.getTransformationMatrix = getTransformationMatrix;
406function multiplyMatrixByVector(transformationMatrix, vector) {
407 var x = vector[0][0] * transformationMatrix[0][0] +
408 vector[1][0] * transformationMatrix[0][1] +
409 vector[2][0] * transformationMatrix[0][2], y = vector[0][0] * transformationMatrix[1][0] +
410 vector[1][0] * transformationMatrix[1][1] +
411 vector[2][0] * transformationMatrix[1][2], z = vector[0][0] * transformationMatrix[2][0] +
412 vector[1][0] * transformationMatrix[2][1] +
413 vector[2][0] * transformationMatrix[2][2];
414 return [[x], [y], [z]];
415}
416exports.multiplyMatrixByVector = multiplyMatrixByVector;
417/**
418 * sameSide
419 *
420 * Calculate whether the current edge's second point, a, (end of first segment)
421 * and its final point, b, are both on the same side of the referenced edge.
422 *
423 * current edge: pipes/hyphens
424 * referenced edge: dots
425 *
426 * Example of True
427 *
428 * p1
429 * .
430 * .
431 * *------------a
432 * . |
433 * . |
434 * . |
435 * . |
436 * . |
437 * . |
438 * . |
439 * . |
440 * . |
441 * . |
442 * . *-----b
443 * .
444 * .
445 * p2
446 *
447 *
448 * Example of False
449 *
450 * p1
451 * .
452 * *------------a
453 * . |
454 * . |
455 * . |
456 * . |
457 * . |
458 * .|
459 * |.
460 * | .
461 * | .
462 * | .
463 * *-----b .
464 * .
465 * p2
466 *
467 *
468 * @param {Object} p1 - first point of the referenced edge
469 * @param {Object} p2 - last point of the referenced edge
470 * @param {Object} a - last point of the first segment of the current edge (the point following the start point)
471 * @param {Object} b - point where the current edge ends
472 * @return {Boolean) - whether the last point of the first segment of the current edge is on the same side as the last point of the current edge
473 */
474function sameSide(p1, p2, a, b) {
475 var bMinusA = [b.x - a.x, b.y - a.y];
476 var p1MinusA = [p1.x - a.x, p1.y - a.y];
477 var p2MinusA = [p2.x - a.x, p2.y - a.y];
478 var crossProduct1 = crossProduct(bMinusA, p1MinusA);
479 var crossProduct2 = crossProduct(bMinusA, p2MinusA);
480 return Math.sign(crossProduct1) === Math.sign(crossProduct2);
481}
482exports.sameSide = sameSide;
483function transform(_a) {
484 var element = _a.element, transformOrigin = _a.transformOrigin, transformationSequence = _a.transformationSequence;
485 var x = element.x, y = element.y, width = element.width, height = element.height;
486 (transformOrigin = transformOrigin || "50% 50%"), (transformationSequence =
487 transformationSequence || []);
488 var transformOriginKeywordMappings = {
489 left: "0%",
490 center: "50%",
491 right: "100%",
492 top: "0%",
493 bottom: "100%"
494 };
495 var transformOriginKeywordMappingsKeys = Object.keys(transformOriginKeywordMappings);
496 var transformOriginPoint = transformOrigin
497 .split(" ")
498 .map(function (value, i) {
499 var numericOrPctValue;
500 var numericValue;
501 if (transformOriginKeywordMappingsKeys.indexOf(value) > -1) {
502 numericOrPctValue = transformOriginKeywordMappings[value];
503 }
504 else {
505 numericOrPctValue = value;
506 }
507 if (numericOrPctValue.indexOf("%") > -1) {
508 var decimalPercent = parseFloat(numericOrPctValue) / 100;
509 if (i === 0) {
510 numericValue = decimalPercent * width;
511 }
512 else {
513 numericValue = decimalPercent * height;
514 }
515 }
516 else if (value.indexOf("em") > -1) {
517 // TODO refactor. this is hacky.
518 numericValue = parseFloat(numericOrPctValue) * 12;
519 }
520 else {
521 numericValue = parseFloat(numericOrPctValue);
522 }
523 if (i === 0) {
524 numericValue += x;
525 }
526 else {
527 numericValue += y;
528 }
529 return numericValue;
530 });
531 // shift origin from top left corner of element bounding box to point specified by transformOrigin (default: center of bounding box)
532 transformationSequence.unshift({
533 key: "translate",
534 value: [transformOriginPoint[0], transformOriginPoint[1]]
535 });
536 // shift origin back to top left corner of element bounding box
537 transformationSequence.push({
538 key: "translate",
539 value: [-1 * transformOriginPoint[0], -1 * transformOriginPoint[1]]
540 });
541 var transformationMatrix = getTransformationMatrix(transformationSequence);
542 var topLeftPoint = [[x], [y], [1]];
543 var bottomRightPoint = [[x + width], [y + height], [1]];
544 var topLeftPointTransformed = multiplyMatrixByVector(transformationMatrix, topLeftPoint);
545 var bottomRightPointTransformed = multiplyMatrixByVector(transformationMatrix, bottomRightPoint);
546 element.x = topLeftPointTransformed[0][0];
547 element.y = topLeftPointTransformed[1][0];
548 element.width = bottomRightPointTransformed[0][0] - element.x;
549 element.height = bottomRightPointTransformed[1][0] - element.y;
550 return element;
551}
552exports.transform = transform;
553//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvbS11dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9nZW9tLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7OztFQWFFOztBQUVGLGlDQUEyQztBQUMzQyxnQ0FBNEU7QUFFNUUsMENBSzBCO0FBQzFCLGlDQUFrQztBQUNsQyx1Q0FBdUM7QUFDdkMscUVBQXFFO0FBQ3JFLGdFQUFnRTtBQUNoRSxnRkFBZ0Y7QUFDaEYsZ0VBQWdFO0FBQ2hFLGdFQUFnRTtBQUNoRSxnREFBa0Q7QUFXbEQseURBQXlEO0FBQ3pELDRDQUE0QztBQUM1QywrQkFBK0I7QUFDL0IsdUJBQXVCO0FBQ3ZCLHlEQUF5RDtBQUN6RCw0Q0FBNEM7QUFFNUMsd0VBQXdFO0FBQ3hFLDhFQUE4RTtBQUM5RSxvREFBb0Q7QUFDdkMsUUFBQSw2QkFBNkIsR0FBRztJQUMzQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2IsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNkLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNiLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztDQUNiLENBQUM7QUFFVyxRQUFBLHNDQUFzQyxHQUFHLGNBQVMsQ0FDN0QsWUFBTyxDQUFDLHFDQUE2QixDQUFDLENBQUMsR0FBRyxDQUFDLFVBQ3pDLEVBQXdCO1FBQXZCLGlCQUFTLEVBQUUsbUJBQVc7SUFFdkIsTUFBTSxDQUFDLENBQUMsU0FBUyxFQUFFLGlCQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDLENBQUMsQ0FDSCxDQUFDO0FBRVcsUUFBQSxzQ0FBc0MsR0FBRyxZQUFPLENBQzNELDhDQUFzQyxDQUN2QyxDQUFDLE1BQU0sQ0FBQyxVQUFTLEdBQUcsRUFBRSxFQUFh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
\No newline at end of file