@rian8337/osu-droid-replay-analyzer 1.4.12-alpha.2 → 1.4.12-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ThreeFingerChecker = void 0;
4
4
  const osu_base_1 = require("@rian8337/osu-base");
5
- const __1 = require("..");
5
+ const hitResult_1 = require("../constants/hitResult");
6
+ const movementType_1 = require("../constants/movementType");
6
7
  const CursorData_1 = require("../data/CursorData");
7
8
  const BeatmapSectionGenerator_1 = require("./BeatmapSectionGenerator");
8
9
  const ThreeFingerBeatmapSection_1 = require("./data/ThreeFingerBeatmapSection");
@@ -49,7 +50,7 @@ class ThreeFingerChecker {
49
50
  * Note that this value does not account for the speed multiplier of
50
51
  * the play, similar to the way replay object data is stored.
51
52
  */
52
- this.maxSectionDeltaTime = 2000;
53
+ this.maxSectionDeltaTime = 1000;
53
54
  /**
54
55
  * The minimum object count required to make a beatmap section.
55
56
  *
@@ -121,7 +122,7 @@ class ThreeFingerChecker {
121
122
  return { is3Finger: false, penalty: 1 };
122
123
  }
123
124
  this.getBeatmapSections();
124
- this.detectDragPlay();
125
+ this.assignFingerIndexes();
125
126
  this.getDetailedBeatmapSections();
126
127
  this.preventAccidentalTaps();
127
128
  if (this.downCursorInstances.filter((v) => v.size > 0).length <= 3) {
@@ -147,11 +148,11 @@ class ThreeFingerChecker {
147
148
  // For sliders and spinners, automatically set hit window length to be as lenient as possible.
148
149
  let beforeIndexHitWindowLength = this.hitWindow.hitWindowFor50(isPrecise);
149
150
  switch (objectData[beforeIndex].result) {
150
- case __1.hitResult.RESULT_300:
151
+ case hitResult_1.hitResult.RESULT_300:
151
152
  beforeIndexHitWindowLength =
152
153
  this.hitWindow.hitWindowFor300(isPrecise);
153
154
  break;
154
- case __1.hitResult.RESULT_100:
155
+ case hitResult_1.hitResult.RESULT_100:
155
156
  beforeIndexHitWindowLength =
156
157
  this.hitWindow.hitWindowFor100(isPrecise);
157
158
  break;
@@ -165,11 +166,11 @@ class ThreeFingerChecker {
165
166
  // For sliders and spinners, automatically set hit window length to be as lenient as possible.
166
167
  let afterIndexHitWindowLength = this.hitWindow.hitWindowFor50(isPrecise);
167
168
  switch (objectData[afterIndex].result) {
168
- case __1.hitResult.RESULT_300:
169
+ case hitResult_1.hitResult.RESULT_300:
169
170
  afterIndexHitWindowLength =
170
171
  this.hitWindow.hitWindowFor300(isPrecise);
171
172
  break;
172
- case __1.hitResult.RESULT_100:
173
+ case hitResult_1.hitResult.RESULT_100:
173
174
  afterIndexHitWindowLength =
174
175
  this.hitWindow.hitWindowFor100(isPrecise);
175
176
  break;
@@ -199,11 +200,11 @@ class ThreeFingerChecker {
199
200
  let firstObjectHitWindow = this.hitWindow.hitWindowFor50(isPrecise);
200
201
  if (objects[0].object instanceof osu_base_1.Circle) {
201
202
  switch (firstObjectResult) {
202
- case __1.hitResult.RESULT_300:
203
+ case hitResult_1.hitResult.RESULT_300:
203
204
  firstObjectHitWindow =
204
205
  this.hitWindow.hitWindowFor300(isPrecise);
205
206
  break;
206
- case __1.hitResult.RESULT_100:
207
+ case hitResult_1.hitResult.RESULT_100:
207
208
  firstObjectHitWindow =
208
209
  this.hitWindow.hitWindowFor100(isPrecise);
209
210
  break;
@@ -216,11 +217,11 @@ class ThreeFingerChecker {
216
217
  let lastObjectHitWindow = this.hitWindow.hitWindowFor50(isPrecise);
217
218
  if (objects.at(-1).object instanceof osu_base_1.Circle) {
218
219
  switch (lastObjectResult) {
219
- case __1.hitResult.RESULT_300:
220
+ case hitResult_1.hitResult.RESULT_300:
220
221
  lastObjectHitWindow =
221
222
  this.hitWindow.hitWindowFor300(isPrecise);
222
223
  break;
223
- case __1.hitResult.RESULT_100:
224
+ case hitResult_1.hitResult.RESULT_100:
224
225
  lastObjectHitWindow =
225
226
  this.hitWindow.hitWindowFor100(isPrecise);
226
227
  break;
@@ -244,7 +245,7 @@ class ThreeFingerChecker {
244
245
  id: [],
245
246
  });
246
247
  for (let j = 0; j < cursorInstance.size; ++j) {
247
- if (cursorInstance.id[j] !== __1.movementType.DOWN) {
248
+ if (cursorInstance.id[j] !== movementType_1.movementType.DOWN) {
248
249
  continue;
249
250
  }
250
251
  const time = cursorInstance.time[j];
@@ -273,162 +274,113 @@ class ThreeFingerChecker {
273
274
  this.beatmapSections.push(new ThreeFingerBeatmapSection_1.ThreeFingerBeatmapSection({
274
275
  firstObjectIndex: beatmapSection.firstObjectIndex,
275
276
  lastObjectIndex: beatmapSection.lastObjectIndex,
276
- isDragged: false,
277
- dragFingerIndex: -1,
277
+ mainFingerIndex: -1,
278
278
  }));
279
279
  }
280
280
  }
281
281
  /**
282
- * Checks whether or not each beatmap sections is dragged.
282
+ * Assigns main finger indexes for each beatmap section.
283
283
  */
284
- detectDragPlay() {
285
- for (let i = 0; i < this.beatmapSections.length; ++i) {
286
- const dragIndex = this.checkDrag(this.beatmapSections[i]);
287
- this.beatmapSections[i].dragFingerIndex = dragIndex;
288
- this.beatmapSections[i].isDragged = dragIndex !== -1;
284
+ assignFingerIndexes() {
285
+ for (const section of this.beatmapSections) {
286
+ let currentIndex = this.getMainFingerIndex(section);
287
+ if (currentIndex === null) {
288
+ const firstObject = this.map.objects[section.firstObjectIndex];
289
+ const firstObjectData = this.data.hitObjectData[section.firstObjectIndex];
290
+ const lastObject = this.map.objects[section.lastObjectIndex];
291
+ const lastObjectData = this.data.hitObjectData[section.lastObjectIndex];
292
+ const startTime = firstObject.object.startTime + firstObjectData.accuracy;
293
+ const endTime = lastObject.object.endTime + lastObjectData.accuracy;
294
+ // Get the cursor instance index in the section that has the most movementType.MOVE instance.
295
+ const moveInstanceAmounts = [];
296
+ for (let i = 0; i < this.data.cursorMovement.length; ++i) {
297
+ let amount = 0;
298
+ const c = this.data.cursorMovement[i];
299
+ for (let j = 0; j < c.size; ++j) {
300
+ if (c.time[j] < startTime) {
301
+ continue;
302
+ }
303
+ if (c.time[j] > endTime) {
304
+ break;
305
+ }
306
+ if (c.id[j] === movementType_1.movementType.MOVE) {
307
+ ++amount;
308
+ }
309
+ }
310
+ moveInstanceAmounts.push(amount);
311
+ }
312
+ currentIndex = moveInstanceAmounts.indexOf(Math.max(...moveInstanceAmounts));
313
+ }
314
+ section.mainFingerIndex = currentIndex;
289
315
  }
290
316
  }
291
317
  /**
292
- * Checks if a section is dragged and returns the index of the drag finger.
293
- *
294
- * If the section is not dragged, -1 will be returned.
318
+ * Gets the main finger index of a beatmap section.
295
319
  *
296
- * @param section The section to check.
320
+ * @param section The beatmap section.
297
321
  */
298
- checkDrag(section) {
299
- const objects = this.map.objects;
300
- const objectData = this.data.hitObjectData;
301
- const isPrecise = this.map.mods.some((m) => m instanceof osu_base_1.ModPrecise);
302
- const firstObject = objects[section.firstObjectIndex];
303
- const lastObject = objects[section.lastObjectIndex];
304
- let firstObjectMinHitTime = firstObject.object.startTime;
305
- if (firstObject.object instanceof osu_base_1.Circle) {
306
- switch (objectData[section.firstObjectIndex].result) {
307
- case __1.hitResult.RESULT_300:
308
- firstObjectMinHitTime -=
309
- this.hitWindow.hitWindowFor300(isPrecise);
310
- break;
311
- case __1.hitResult.RESULT_100:
312
- firstObjectMinHitTime -=
313
- this.hitWindow.hitWindowFor100(isPrecise);
314
- break;
315
- default:
316
- firstObjectMinHitTime -=
317
- this.hitWindow.hitWindowFor50(isPrecise);
318
- }
319
- }
320
- else {
321
- firstObjectMinHitTime -= this.hitWindow.hitWindowFor50(isPrecise);
322
- }
323
- let lastObjectMaxHitTime = lastObject.object.startTime;
324
- if (lastObject.object instanceof osu_base_1.Circle) {
325
- switch (objectData[section.lastObjectIndex].result) {
326
- case __1.hitResult.RESULT_300:
327
- lastObjectMaxHitTime +=
328
- this.hitWindow.hitWindowFor300(isPrecise);
329
- break;
330
- case __1.hitResult.RESULT_100:
331
- lastObjectMaxHitTime +=
332
- this.hitWindow.hitWindowFor100(isPrecise);
333
- break;
334
- default:
335
- lastObjectMaxHitTime +=
336
- this.hitWindow.hitWindowFor50(isPrecise);
337
- }
338
- }
339
- else {
340
- lastObjectMaxHitTime += this.hitWindow.hitWindowFor50(isPrecise);
341
- }
342
- // Since there may be more than 1 cursor instance index,
343
- // we check which cursor instance follows hitobjects all over.
344
- const cursorIndexes = [];
322
+ getMainFingerIndex(section) {
323
+ const validCursorIndexes = new Set();
324
+ const timeDiscrepancy = 10;
345
325
  for (let i = 0; i < this.data.cursorMovement.length; ++i) {
346
- const c = this.data.cursorMovement[i];
347
- if (c.size === 0) {
348
- continue;
349
- }
350
- // Do not include cursors that don't have an occurence in this section
351
- // this speeds up checking process.
352
- if (c.time.filter((v) => v >= firstObjectMinHitTime && v <= lastObjectMaxHitTime).length === 0) {
353
- continue;
326
+ if (this.data.cursorMovement[i].size > 0) {
327
+ validCursorIndexes.add(i);
354
328
  }
355
- // If this cursor instance doesn't move, it's not the cursor instance we want.
356
- if (c.id.filter((v) => v === __1.movementType.MOVE).length === 0) {
357
- continue;
358
- }
359
- cursorIndexes.push(i);
360
- }
361
- return this.findDragIndex(objects.slice(section.firstObjectIndex, section.lastObjectIndex + 1), objectData.slice(section.firstObjectIndex, section.lastObjectIndex + 1), cursorIndexes);
362
- }
363
- /**
364
- * Finds the drag index of the section.
365
- *
366
- * @param sectionObjects The objects in the section.
367
- * @param sectionReplayObjectData The hitobject data of all objects in the section.
368
- * @param cursorIndexes The indexes of the cursor instance that has at least an occurrence in the section.
369
- */
370
- findDragIndex(sectionObjects, sectionReplayObjectData, cursorIndexes) {
371
- let objectIndex = sectionObjects.findIndex((v, i) => !(v.object instanceof osu_base_1.Spinner) &&
372
- sectionReplayObjectData[i].result !== __1.hitResult.RESULT_0);
373
- if (objectIndex === -1) {
374
- return -1;
375
329
  }
376
- while (cursorIndexes.length > 0) {
377
- if (objectIndex === sectionObjects.length) {
330
+ for (let i = section.firstObjectIndex; i <= section.lastObjectIndex; ++i) {
331
+ if (validCursorIndexes.size === 1) {
378
332
  break;
379
333
  }
380
- const o = sectionObjects[objectIndex];
381
- const s = sectionReplayObjectData[objectIndex];
382
- ++objectIndex;
383
- if (s.result === __1.hitResult.RESULT_0) {
334
+ const object = this.map.objects[i];
335
+ if (object.object instanceof osu_base_1.Spinner) {
384
336
  continue;
385
337
  }
386
- // Get the cursor instance that is closest to the object's hit time.
387
- for (let j = 0; j < cursorIndexes.length; ++j) {
388
- const c = this.data.cursorMovement[cursorIndexes[j]];
389
- // Cursor instances aren't always recorded at all times,
390
- // therefore the game emulates the movement between
391
- // movementType.MOVE cursors.
392
- const hitTime = o.object.startTime + s.accuracy;
393
- const nextHitIndex = c.time.findIndex((v) => v >= hitTime);
394
- const hitIndex = nextHitIndex - 1;
395
- if (hitIndex <= -1) {
396
- cursorIndexes[j] = -1;
397
- continue;
398
- }
399
- if (c.id[hitIndex] === __1.movementType.UP) {
400
- cursorIndexes[j] = -1;
338
+ const objectData = this.data.hitObjectData[i];
339
+ const hitTime = object.startTime + objectData.accuracy;
340
+ for (let j = 0; j < this.data.cursorMovement.length; ++j) {
341
+ if (!validCursorIndexes.has(j)) {
401
342
  continue;
402
343
  }
403
- const cursorPosition = new osu_base_1.Vector2(c.x[hitIndex], c.y[hitIndex]);
404
- let isInObject = false;
405
- if (c.id[nextHitIndex] === __1.movementType.MOVE ||
406
- c.id[hitIndex] === __1.movementType.MOVE) {
407
- // Try to interpolate movement between two movementType.MOVE cursor every 1ms.
408
- // This minimizes rounding error.
409
- for (let mSecPassed = c.time[hitIndex]; mSecPassed <= c.time[nextHitIndex]; ++mSecPassed) {
410
- const t = (mSecPassed - c.time[nextHitIndex]) /
411
- (c.time[hitIndex] - c.time[nextHitIndex]);
412
- cursorPosition.x = osu_base_1.Interpolation.lerp(c.x[hitIndex], c.x[nextHitIndex], t);
413
- cursorPosition.y = osu_base_1.Interpolation.lerp(c.y[hitIndex], c.y[nextHitIndex], t);
414
- if (o.object.stackedPosition.getDistance(cursorPosition) <= o.object.radius) {
415
- isInObject = true;
416
- break;
344
+ const c = this.data.cursorMovement[j];
345
+ for (let k = 0; k < c.size; ++k) {
346
+ if (c.time[k] < hitTime - timeDiscrepancy ||
347
+ c.id[k] === movementType_1.movementType.UP) {
348
+ continue;
349
+ }
350
+ if (c.time[k] > hitTime + timeDiscrepancy) {
351
+ break;
352
+ }
353
+ // Calculate the initial cursor position assuming it's a DOWN movement type.
354
+ const cursorPosition = new osu_base_1.Vector2(c.x[k], c.y[k]);
355
+ let isInObject = false;
356
+ // But if the next cursor is a move instance, then we extend through
357
+ // time between both cursors and interpolate cursor position.
358
+ if (c.id[k + 1] === movementType_1.movementType.MOVE) {
359
+ // Loop every 1ms to increase accuracy and minimalize error.
360
+ for (let mSecPassed = c.time[k]; mSecPassed <= c.time[k + 1]; ++mSecPassed) {
361
+ const t = (mSecPassed - c.time[k + 1]) /
362
+ (c.time[k] - c.time[k + 1]);
363
+ cursorPosition.x = osu_base_1.Interpolation.lerp(c.x[k], c.x[k + 1], t);
364
+ cursorPosition.y = osu_base_1.Interpolation.lerp(c.y[k], c.y[k + 1], t);
365
+ if (object.object.stackedPosition.getDistance(cursorPosition) <= object.object.radius) {
366
+ isInObject = true;
367
+ break;
368
+ }
417
369
  }
418
370
  }
419
- }
420
- else {
421
- isInObject =
422
- o.object.stackedPosition.getDistance(cursorPosition) <=
423
- o.object.radius;
424
- }
425
- if (!isInObject) {
426
- cursorIndexes[j] = -1;
371
+ else {
372
+ isInObject =
373
+ object.object.stackedPosition.getDistance(cursorPosition) <= object.object.radius;
374
+ }
375
+ if (!isInObject) {
376
+ validCursorIndexes.delete(j);
377
+ break;
378
+ }
427
379
  }
428
380
  }
429
- cursorIndexes = cursorIndexes.filter((v) => v !== -1);
430
381
  }
431
- return cursorIndexes.shift() ?? -1;
382
+ const [first] = validCursorIndexes;
383
+ return first ?? null;
432
384
  }
433
385
  /**
434
386
  * Redivides the beatmap into sections.
@@ -457,18 +409,15 @@ class ThreeFingerChecker {
457
409
  newBeatmapSections.push({
458
410
  firstObjectIndex: newFirstObjectIndex,
459
411
  lastObjectIndex: i,
460
- isDragged: beatmapSection.isDragged,
461
- dragFingerIndex: beatmapSection.dragFingerIndex,
412
+ mainFingerIndex: beatmapSection.mainFingerIndex,
462
413
  });
463
414
  }
464
415
  }
465
416
  // Don't forget to manually add the last beatmap section, which would otherwise be ignored.
466
417
  if (inSpeedSection) {
467
418
  newBeatmapSections.push({
419
+ ...beatmapSection,
468
420
  firstObjectIndex: newFirstObjectIndex,
469
- lastObjectIndex: beatmapSection.lastObjectIndex,
470
- isDragged: beatmapSection.isDragged,
471
- dragFingerIndex: beatmapSection.dragFingerIndex,
472
421
  });
473
422
  }
474
423
  }
@@ -525,15 +474,15 @@ class ThreeFingerChecker {
525
474
  // We only filter cursor instances that are above the strain threshold.
526
475
  // This minimalizes the amount of cursor instances to analyze.
527
476
  for (const beatmapSection of this.beatmapSections) {
528
- const dragIndex = beatmapSection.dragFingerIndex;
477
+ const mainIndex = beatmapSection.mainFingerIndex;
529
478
  const startTime = objects[beatmapSection.firstObjectIndex].object.startTime +
530
479
  (objectData[beatmapSection.firstObjectIndex].result !==
531
- __1.hitResult.RESULT_0
480
+ hitResult_1.hitResult.RESULT_0
532
481
  ? objectData[beatmapSection.firstObjectIndex].accuracy
533
482
  : -this.hitWindow.hitWindowFor50(isPrecise));
534
483
  const endTime = objects[beatmapSection.lastObjectIndex].object.endTime +
535
484
  (objectData[beatmapSection.lastObjectIndex].result !==
536
- __1.hitResult.RESULT_0
485
+ hitResult_1.hitResult.RESULT_0
537
486
  ? objectData[beatmapSection.lastObjectIndex].accuracy
538
487
  : this.hitWindow.hitWindowFor50(isPrecise));
539
488
  // Filter cursor instances during section.
@@ -550,10 +499,6 @@ class ThreeFingerChecker {
550
499
  const cursorAmounts = [];
551
500
  const cursorVectorTimes = [];
552
501
  for (let i = 0; i < this.downCursorInstances.length; ++i) {
553
- // Do not include drag cursor instance.
554
- if (i === dragIndex) {
555
- continue;
556
- }
557
502
  const cursorData = this.downCursorInstances[i];
558
503
  let amount = 0;
559
504
  for (let j = 0; j < cursorData.size; ++j) {
@@ -568,18 +513,25 @@ class ThreeFingerChecker {
568
513
  }
569
514
  cursorAmounts.push(amount);
570
515
  }
571
- // This index will be used to detect if a section is 3-fingered.
572
- // If the section is dragged, the dragged instance will be ignored,
573
- // hence why the index is 1 less than nondragged section.
574
- const fingerSplitIndex = dragIndex !== -1 ? 2 : 3;
575
- // Divide >=4th (3rd for drag) cursor instances with 1st + 2nd (+ 3rd for nondrag)
576
- // to check if the section is 3-fingered.
577
- const threeFingerRatio = cursorAmounts
578
- .slice(fingerSplitIndex)
579
- .reduce((acc, value) => acc + value, 0) /
580
- cursorAmounts
581
- .slice(0, fingerSplitIndex)
582
- .reduce((acc, value) => acc + value, 0);
516
+ let validCursorPressCount = 0;
517
+ let invalidCursorPressCount = 0;
518
+ const validIndexes = [];
519
+ for (let i = 0; i < cursorAmounts.length; ++i) {
520
+ // Ignore the main cursor index.
521
+ if (i === mainIndex) {
522
+ continue;
523
+ }
524
+ // Add 2f cursor presses to valid cursor count and the rest to invalid cursor count.
525
+ if (validIndexes.length <= 2) {
526
+ validCursorPressCount += cursorAmounts[i];
527
+ }
528
+ else {
529
+ invalidCursorPressCount += cursorAmounts[i];
530
+ }
531
+ validIndexes.push(i);
532
+ }
533
+ validIndexes.push(mainIndex);
534
+ const threeFingerRatio = invalidCursorPressCount / validCursorPressCount;
583
535
  const similarPresses = [];
584
536
  for (const cursorVectorTime of cursorVectorTimes) {
585
537
  const pressIndex = similarPresses.findIndex((v) => v.vector.getDistance(cursorVectorTime.vector) <=
@@ -627,25 +579,29 @@ class ThreeFingerChecker {
627
579
  .slice(beatmapSection.firstObjectIndex, beatmapSection.lastObjectIndex)
628
580
  .reduce((acc, value) => acc +
629
581
  value.originalTapStrain /
630
- ThreeFingerChecker.strainThreshold, 0), 0.85);
631
- // We can ignore the first 3 (2 for drag) filled cursor instances
632
- // since they are guaranteed not 3 finger.
633
- const threeFingerCursorAmounts = cursorAmounts
634
- .slice(fingerSplitIndex)
635
- .filter((amount) => amount > 0);
582
+ ThreeFingerChecker.strainThreshold, 0), 0.875);
636
583
  // Finger factor applies more penalty if more fingers were used.
637
- const fingerFactor = threeFingerRatio > this.threeFingerRatioThreshold
638
- ? threeFingerCursorAmounts.reduce((acc, value, index) => acc +
639
- Math.pow(((index + 1) * value * objectCount) /
640
- this.strainNoteCount, 0.8), 1)
641
- : Math.pow(validPresses.reduce((acc, value, index) => acc +
584
+ let fingerFactor = 1;
585
+ if (threeFingerRatio > this.threeFingerRatioThreshold) {
586
+ for (let i = 0, penaltyIndex = 1; i < cursorAmounts.length; ++i) {
587
+ if (validIndexes.includes(i)) {
588
+ continue;
589
+ }
590
+ fingerFactor += Math.pow((penaltyIndex * cursorAmounts[i] * objectCount) /
591
+ this.strainNoteCount, 0.8);
592
+ ++penaltyIndex;
593
+ }
594
+ }
595
+ else {
596
+ fingerFactor = Math.pow(validPresses.reduce((acc, value, index) => acc +
642
597
  Math.pow(((index + 1) *
643
598
  (value.count /
644
599
  (this
645
600
  .cursorDistancingCountThreshold *
646
601
  2)) *
647
602
  objectCount) /
648
- this.strainNoteCount, 0.2), 1), 0.2);
603
+ this.strainNoteCount, 0.2), 1), 0.25);
604
+ }
649
605
  // Length factor applies more penalty if there are more 3-fingered object.
650
606
  const lengthFactor = 1 + Math.pow(objectCount / this.strainNoteCount, 1.2);
651
607
  this.nerfFactors.push({
@@ -3,13 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ThreeFingerBeatmapSection = void 0;
4
4
  const BeatmapSection_1 = require("./BeatmapSection");
5
5
  /**
6
- * A section of a beatmap. This is used to detect dragged sections.
6
+ * A section of a beatmap with extra information used for detecting three-finger usage.
7
7
  */
8
8
  class ThreeFingerBeatmapSection extends BeatmapSection_1.BeatmapSection {
9
9
  constructor(values) {
10
10
  super(values.firstObjectIndex, values.lastObjectIndex);
11
- this.isDragged = values.isDragged;
12
- this.dragFingerIndex = values.dragFingerIndex;
11
+ this.mainFingerIndex = values.mainFingerIndex;
13
12
  }
14
13
  }
15
14
  exports.ThreeFingerBeatmapSection = ThreeFingerBeatmapSection;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-droid-replay-analyzer",
3
- "version": "1.4.12-alpha.2",
3
+ "version": "1.4.12-alpha.5",
4
4
  "description": "A replay analyzer for analyzing osu!droid replay files.",
5
5
  "keywords": [
6
6
  "osu",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@rian8337/osu-base": "^1.4.8",
35
35
  "@rian8337/osu-difficulty-calculator": "^1.4.8",
36
- "@rian8337/osu-rebalance-difficulty-calculator": "^1.4.12-alpha.2",
36
+ "@rian8337/osu-rebalance-difficulty-calculator": "^1.4.12-alpha.4",
37
37
  "java-deserialization": "^0.1.0",
38
38
  "unzipper": "^0.10.11"
39
39
  },
@@ -45,5 +45,5 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
- "gitHead": "9e03096bfdc8a36d6227b1c3723afba845ba92d7"
48
+ "gitHead": "9e42f2db1fa53115f7dcca1a6f09802267c3fe29"
49
49
  }