diff --git a/README.md b/README.md
index 91b27c0..630c413 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ These instructions will get you a copy of the project up and running on your loc
### Prerequisites
-- Node.js 8+
+- Node.js 8.3.0+
### Installing
@@ -58,4 +58,4 @@ request.get('https://osu.ppy.sh/osu/1262832').then(osu => {
## License
-This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
\ No newline at end of file
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
diff --git a/package.json b/package.json
index 6bd9e33..c297192 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,12 @@
{
"name": "osu-bpdpc",
- "version": "0.2.2",
+ "version": "0.2.3",
"description": "Osu beatmap parser, difficulty and performance calculator",
"main": "index.js",
+ "engines": {
+ "node": ">=8.3.0",
+ "npm": ">=5.3.0"
+ },
"scripts": {
"test": "mocha src/**/*.spec.js",
"lint": "eslint **/*.{js,ts} && tsc"
diff --git a/src/Utils/PathApproximator.js b/src/Utils/PathApproximator.js
index aa10d21..f3f3b64 100644
--- a/src/Utils/PathApproximator.js
+++ b/src/Utils/PathApproximator.js
@@ -1,18 +1,18 @@
const Vector2 = require('./Vector2');
+const bezier_tolerance = Math.fround(0.25);
+const circular_arc_tolerance = Math.fround(0.1);
+
+/**
+ * The amount of pieces to calculate for each control point quadruplet.
+ */
+const catmull_detail = 50;
+
/**
* Helper methods to approximate a path by interpolating a sequence of control points.
*/
class PathApproximator
{
- static #bezier_tolerance = Math.fround(0.25);
- static #circular_arc_tolerance = Math.fround(0.1);
-
- /**
- * The amount of pieces to calculate for each control point quadruplet.
- */
- static #catmull_detail = 50;
-
/**
* Creates a piecewise-linear approximation of a bezier curve, by adaptively repeatedly subdividing
* the control points until their approximation error vanishes below a given threshold.
@@ -38,12 +38,12 @@ class PathApproximator
while (toFlatten.length > 0) {
let parent = toFlatten.pop();
- if (PathApproximator.#bezierIsFlatEnough(parent)) {
+ if (PathApproximator._bezierIsFlatEnough(parent)) {
// If the control points we currently operate on are sufficiently "flat", we use
// an extension to De Casteljau's algorithm to obtain a piecewise-linear approximation
// of the bezier curve represented by our control points, consisting of the same amount
// of points as there are control points.
- PathApproximator.#bezierApproximate(parent, output, subdivisionBuffer1, subdivisionBuffer2, count);
+ PathApproximator._bezierApproximate(parent, output, subdivisionBuffer1, subdivisionBuffer2, count);
freeBuffers.push(parent);
continue;
@@ -53,7 +53,7 @@ class PathApproximator
// subdividing the curve we are currently operating on.
let rightChild = freeBuffers.length > 0 ? freeBuffers.pop() : [];
- PathApproximator.#bezierSubdivide(parent, leftChild, rightChild, subdivisionBuffer1, count);
+ PathApproximator._bezierSubdivide(parent, leftChild, rightChild, subdivisionBuffer1, count);
// We re-use the buffer of the parent for one of the children, so that we save one allocation per iteration.
for (let i = 0; i < count; ++i) {
@@ -84,9 +84,9 @@ class PathApproximator
let v3 = i < controlPointsLength - 1 ? controlPoints[i + 1] : v2.add(v2).subtract(v1);
let v4 = i < controlPointsLength - 2 ? controlPoints[i + 2] : v3.add(v3).subtract(v2);
- for (let c = 0; c < PathApproximator.#catmull_detail; c++) {
- result.push(PathApproximator.#catmullFindPoint(v1, v2, v3, v4, Math.fround(c) / PathApproximator.#catmull_detail));
- result.push(PathApproximator.#catmullFindPoint(v1, v2, v3, v4, Math.fround(c + 1) / PathApproximator.#catmull_detail));
+ for (let c = 0; c < catmull_detail; c++) {
+ result.push(PathApproximator._catmullFindPoint(v1, v2, v3, v4, Math.fround(c) / catmull_detail));
+ result.push(PathApproximator._catmullFindPoint(v1, v2, v3, v4, Math.fround(c + 1) / catmull_detail));
}
}
@@ -157,8 +157,8 @@ class PathApproximator
// is: 2 * Math.Acos(1 - TOLERANCE / r)
// The special case is required for extremely short sliders where the radius is smaller than
// the tolerance. This is a pathological rather than a realistic case.
- let amountPoints = 2 * r <= PathApproximator.#circular_arc_tolerance ? 2
- : Math.max(2, Math.ceil(thetaRange / (2 * Math.acos(1 - PathApproximator.#circular_arc_tolerance / r))));
+ let amountPoints = 2 * r <= circular_arc_tolerance ? 2
+ : Math.max(2, Math.ceil(thetaRange / (2 * Math.acos(1 - circular_arc_tolerance / r))));
let output = [];
let fract, theta, o;
@@ -196,7 +196,7 @@ class PathApproximator
let result = [];
- let weights = PathApproximator.#barycentricWeights(controlPoints);
+ let weights = PathApproximator._barycentricWeights(controlPoints);
let minX = controlPoints[0].x;
let maxX = controlPoints[0].x;
@@ -210,7 +210,7 @@ class PathApproximator
for (let i = 0; i < num_steps; i++) {
let x = minX + dx / (num_steps - 1) * i;
- let y = Math.fround(PathApproximator.#barycentricLagrange(controlPoints, weights, x));
+ let y = Math.fround(PathApproximator._barycentricLagrange(controlPoints, weights, x));
result.push(new Vector2(x, y));
}
@@ -223,7 +223,7 @@ class PathApproximator
* Can be used as a helper function to compute a Lagrange polynomial repeatedly.
* @param points An array of coordinates. No two x should be the same.
*/
- static #barycentricWeights(points)
+ static _barycentricWeights(points)
{
let n = points.length;
let w = [];
@@ -249,7 +249,7 @@ class PathApproximator
* @param weights An array of precomputed barycentric weights.
* @param time The x coordinate to calculate the basis polynomial for.
*/
- static #barycentricLagrange(points, weights, time)
+ static _barycentricLagrange(points, weights, time)
{
if (points === null || points.Length === 0) {
throw new Error("points must contain at least one point");
@@ -285,7 +285,7 @@ class PathApproximator
* @param controlPoints The control points to check for flatness.
* @returns Whether the control points are flat enough.
*/
- static #bezierIsFlatEnough(controlPoints)
+ static _bezierIsFlatEnough(controlPoints)
{
let sub, sum, scale;
@@ -294,7 +294,7 @@ class PathApproximator
sub = controlPoints[i - 1].subtract(scale);
sum = sub.add(controlPoints[i + 1]);
- if (sum.length() ** 2 > PathApproximator.#bezier_tolerance ** 2 * 4) {
+ if (sum.length() ** 2 > bezier_tolerance ** 2 * 4) {
return false;
}
}
@@ -312,7 +312,7 @@ class PathApproximator
* @param subdivisionBuffer The first buffer containing the current subdivision state.
* @param count The number of control points in the original list.
*/
- static #bezierSubdivide(controlPoints, l, r, subdivisionBuffer, count)
+ static _bezierSubdivide(controlPoints, l, r, subdivisionBuffer, count)
{
let midpoints = subdivisionBuffer;
@@ -339,12 +339,12 @@ class PathApproximator
* @param subdivisionBuffer1 The first buffer containing the current subdivision state.
* @param subdivisionBuffer2 The second buffer containing the current subdivision state.
*/
- static #bezierApproximate(controlPoints, output, subdivisionBuffer1, subdivisionBuffer2, count)
+ static _bezierApproximate(controlPoints, output, subdivisionBuffer1, subdivisionBuffer2, count)
{
let l = subdivisionBuffer2;
let r = subdivisionBuffer1;
- PathApproximator.#bezierSubdivide(controlPoints, l, r, subdivisionBuffer1, count);
+ PathApproximator._bezierSubdivide(controlPoints, l, r, subdivisionBuffer1, count);
for (let i = 0; i < count - 1; ++i) {
l[count + i] = r[i + 1];
@@ -369,7 +369,7 @@ class PathApproximator
* @param t The parameter at which to find the point on the spline, in the range [0, 1].
* @returns The point on the spline at t.
*/
- static #catmullFindPoint(vec1, vec2, vec3, vec4, t)
+ static _catmullFindPoint(vec1, vec2, vec3, vec4, t)
{
let t2 = Math.fround(t * t);
let t3 = Math.fround(t * t2);
diff --git a/src/Utils/SliderPath.js b/src/Utils/SliderPath.js
index 678466a..1912974 100644
--- a/src/Utils/SliderPath.js
+++ b/src/Utils/SliderPath.js
@@ -3,26 +3,18 @@ const Vector2 = require('./Vector2');
class SliderPath
{
- /**
- * The user-set distance of the path. If non-null, will match this value,
- * and the path will be shortened/lengthened to match this length.
- */
- expectedDistance;
-
- /**
- * The control points of the path.
- */
- controlPoints;
-
- calculatedPath;
- cumulativeLength;
- #pathCache;
-
- calculatedLength;
constructor(controlPoints, expectedDistance = null)
{
+ /**
+ * The control points of the path.
+ */
this.controlPoints = controlPoints.slice();
+
+ /**
+ * The user-set distance of the path. If non-null, will match this value,
+ * and the path will be shortened/lengthened to match this length.
+ */
this.expectedDistance = expectedDistance;
}
@@ -31,7 +23,7 @@ class SliderPath
*/
get distance()
{
- this.#ensureValid();
+ this._ensureValid();
return this.cumulativeLength.length === 0
? 0 : this.cumulativeLength[this.cumulativeLength.length - 1];
@@ -42,7 +34,7 @@ class SliderPath
*/
get calculatedDistance()
{
- this.#ensureValid();
+ this._ensureValid();
return this.calculatedLength;
}
@@ -56,22 +48,22 @@ class SliderPath
*/
getPathToProgress(path, p0, p1)
{
- this.#ensureValid();
+ this._ensureValid();
- let d0 = this.#progressToDistance(p0);
- let d1 = this.#progressToDistance(p1);
+ let d0 = this._progressToDistance(p0);
+ let d1 = this._progressToDistance(p1);
let i = 0;
while (i < this.calculatedPath.length && this.cumulativeLength[i++] < d0);
- path = [this.#interpolateVertices(i, d0)];
+ path = [this._interpolateVertices(i, d0)];
while (i < this.calculatedPath.length && this.cumulativeLength[i++] <= d1) {
path.push(this.calculatedPath[i]);
}
- path.push(this.#interpolateVertices(i, d1));
+ path.push(this._interpolateVertices(i, d1));
}
/**
@@ -81,26 +73,26 @@ class SliderPath
*/
positionAt(progress)
{
- this.#ensureValid();
+ this._ensureValid();
- let d = this.#progressToDistance(progress);
+ let d = this._progressToDistance(progress);
- return this.#interpolateVertices(this.#indexOfDistance(d), d);
+ return this._interpolateVertices(this._indexOfDistance(d), d);
}
- #ensureValid()
+ _ensureValid()
{
- if (this.#pathCache) {
+ if (this._pathCache) {
return;
}
- this.#calculatePath();
- this.#calculateLength();
+ this._calculatePath();
+ this._calculateLength();
- this.#pathCache = true;
+ this._pathCache = true;
}
- #calculatePath()
+ _calculatePath()
{
let controlPointsLength = this.controlPoints.length;
@@ -127,7 +119,7 @@ class SliderPath
let segmentVertices = vertices.slice(start, i + 1);
let segmentType = this.controlPoints[start].type || 'L';
- for (let t of this.#calculateSubPath(segmentVertices, segmentType)) {
+ for (let t of this._calculateSubPath(segmentVertices, segmentType)) {
if (this.calculatedPath.length === 0
|| this.calculatedPath[this.calculatedPath.length - 1] != t) {
this.calculatedPath.push(t);
@@ -139,7 +131,7 @@ class SliderPath
}
}
- #calculateSubPath(subControlPoints, type)
+ _calculateSubPath(subControlPoints, type)
{
switch (type) {
case 'L':
@@ -167,7 +159,7 @@ class SliderPath
return PathApproximator.approximateBezier(subControlPoints);
}
- #calculateLength()
+ _calculateLength()
{
this.calculatedLength = 0;
this.cumulativeLength = [0];
@@ -212,16 +204,16 @@ class SliderPath
}
}
- #indexOfDistance(d)
+ _indexOfDistance(d)
{
- let i = this.#binarySearch(this.cumulativeLength, d);
+ let i = this._binarySearch(this.cumulativeLength, d);
if (i < 0) i = ~i;
return i;
}
- #binarySearch(arr, x)
+ _binarySearch(arr, x)
{
let start = 0, mid, end = arr.length - 1;
@@ -242,12 +234,12 @@ class SliderPath
return Math.floor((start + end) / 2);
}
- #progressToDistance(progress)
+ _progressToDistance(progress)
{
return Math.min(Math.max(progress, 0), 1) * this.distance;
}
- #interpolateVertices(i, d)
+ _interpolateVertices(i, d)
{
if (this.calculatedPath.length === 0)
return new Vector2(0, 0);