@rian8337/osu-strain-graph-generator 4.0.0-beta.92 → 4.0.0-beta.94

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.
Files changed (2) hide show
  1. package/dist/index.js +55 -16
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -339,6 +339,27 @@ class Chart {
339
339
  }
340
340
  }
341
341
 
342
+ /**
343
+ * Creates a sampler function that retrieves the value of the most recent peak at or before a given time.
344
+ *
345
+ * Peaks of different skills can represent sections of different (and possibly variable) lengths, or even
346
+ * one peak per hitobject, so they cannot be assumed to share a common, fixed-width time grid. This walks
347
+ * a single chronologically sorted `peaks` array forward as `time` increases, treating each peak as holding
348
+ * its value until the next peak takes over.
349
+ *
350
+ * @param peaks The peaks to sample from, in chronological order.
351
+ */
352
+ function createSampler(peaks) {
353
+ let index = -1;
354
+ let value = 0;
355
+ return (time) => {
356
+ while (index + 1 < peaks.length && peaks[index + 1].time <= time) {
357
+ ++index;
358
+ value = peaks[index].value;
359
+ }
360
+ return value;
361
+ };
362
+ }
342
363
  /**
343
364
  * Generates the strain chart of a beatmap and returns the chart as a buffer.
344
365
  *
@@ -349,37 +370,55 @@ class Chart {
349
370
  */
350
371
  function index (beatmap, strainPeaks, clockRate, options) {
351
372
  return __awaiter(this, void 0, void 0, function* () {
352
- var _a, _b, _c, _d, _e, _f, _g, _h;
373
+ var _a, _b, _c, _d, _e;
353
374
  const sectionLength = 400;
354
- const currentSectionEnd = Math.ceil(beatmap.hitObjects.objects[0].startTime / sectionLength) *
355
- sectionLength;
356
- const strainInformations = new Array(Math.max(strainPeaks.aimWithSliders.length, strainPeaks.speed.length, strainPeaks.flashlight.length) + 1);
375
+ const hasFlashlight = strainPeaks.flashlight.length > 0;
376
+ // Each skill's peaks may be sectioned differently (fixed-width sections, variable-length sections,
377
+ // or one peak per hitobject), so they are merged onto the union of their own timestamps rather than
378
+ // a shared, assumed-uniform grid.
379
+ const timestamps = new Set();
380
+ for (const peak of strainPeaks.aimWithSliders) {
381
+ timestamps.add(peak.time);
382
+ }
383
+ for (const peak of strainPeaks.speed) {
384
+ timestamps.add(peak.time);
385
+ }
386
+ for (const peak of strainPeaks.flashlight) {
387
+ timestamps.add(peak.time);
388
+ }
389
+ const sortedTimestamps = [...timestamps].sort((a, b) => a - b);
390
+ const firstObjectStartTime = beatmap.hitObjects.objects[0].startTime / clockRate;
391
+ const sampleAim = createSampler(strainPeaks.aimWithSliders);
392
+ const sampleSpeed = createSampler(strainPeaks.speed);
393
+ const sampleFlashlight = createSampler(strainPeaks.flashlight);
394
+ const strainInformations = new Array(sortedTimestamps.length + 1);
357
395
  // Intentionally insert a 0 strain at 400ms less than the beginning
358
396
  // of the first object to smoothen the end curve.
359
397
  strainInformations[0] = {
360
398
  strain: 0,
361
- time: (currentSectionEnd - sectionLength) / 1000,
399
+ time: (firstObjectStartTime - sectionLength) / 1000,
362
400
  };
363
- for (let i = 1; i < strainInformations.length; ++i) {
364
- const aimStrain = (_a = strainPeaks.aimWithSliders[i]) !== null && _a !== void 0 ? _a : 0;
365
- const speedStrain = (_b = strainPeaks.speed[i]) !== null && _b !== void 0 ? _b : 0;
366
- const flashlightStrain = (_c = strainPeaks.flashlight[i]) !== null && _c !== void 0 ? _c : 0;
367
- strainInformations[i] = {
368
- time: (currentSectionEnd + sectionLength * (i - 1)) / 1000,
369
- strain: strainPeaks.flashlight.length > 0
401
+ for (let i = 0; i < sortedTimestamps.length; ++i) {
402
+ const time = sortedTimestamps[i];
403
+ const aimStrain = sampleAim(time);
404
+ const speedStrain = sampleSpeed(time);
405
+ const flashlightStrain = sampleFlashlight(time);
406
+ strainInformations[i + 1] = {
407
+ time: time / 1000,
408
+ strain: hasFlashlight
370
409
  ? (aimStrain + speedStrain + flashlightStrain) / 3
371
410
  : (aimStrain + speedStrain) / 2,
372
411
  };
373
412
  }
374
- const maxTime = (_e = (_d = strainInformations.at(-1)) === null || _d === void 0 ? void 0 : _d.time) !== null && _e !== void 0 ? _e : beatmap.hitObjects.objects.at(-1).endTime / 1000 / clockRate;
413
+ const maxTime = (_b = (_a = strainInformations.at(-1)) === null || _a === void 0 ? void 0 : _a.time) !== null && _b !== void 0 ? _b : beatmap.hitObjects.objects.at(-1).endTime / 1000 / clockRate;
375
414
  const maxStrain = Math.max(osuBase.MathUtils.max(strainInformations.map((v) => v.strain)), 1);
376
415
  const maxXUnits = 10;
377
416
  const maxYUnits = 10;
378
417
  const unitsPerTickX = Math.ceil(maxTime / maxXUnits / 10) * 10;
379
418
  const unitsPerTickY = maxStrain / maxYUnits / 20;
380
419
  const chart = new Chart({
381
- graphWidth: (_f = options === null || options === void 0 ? void 0 : options.width) !== null && _f !== void 0 ? _f : 600,
382
- graphHeight: (_g = options === null || options === void 0 ? void 0 : options.height) !== null && _g !== void 0 ? _g : 150,
420
+ graphWidth: (_c = options === null || options === void 0 ? void 0 : options.width) !== null && _c !== void 0 ? _c : 600,
421
+ graphHeight: (_d = options === null || options === void 0 ? void 0 : options.height) !== null && _d !== void 0 ? _d : 150,
383
422
  minX: 0,
384
423
  minY: 0,
385
424
  maxX: Math.ceil(maxTime / unitsPerTickX) * unitsPerTickX,
@@ -404,7 +443,7 @@ function index (beatmap, strainPeaks, clockRate, options) {
404
443
  pointRadius: 0,
405
444
  xValueType: "time",
406
445
  });
407
- chart.drawArea(strainInformations.map((v) => new osuBase.Vector2(v.time, v.strain)), (_h = options === null || options === void 0 ? void 0 : options.color) !== null && _h !== void 0 ? _h : "#000000");
446
+ chart.drawArea(strainInformations.map((v) => new osuBase.Vector2(v.time, v.strain)), (_e = options === null || options === void 0 ? void 0 : options.color) !== null && _e !== void 0 ? _e : "#000000");
408
447
  return chart.getBuffer();
409
448
  });
410
449
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-strain-graph-generator",
3
- "version": "4.0.0-beta.92",
3
+ "version": "4.0.0-beta.94",
4
4
  "description": "A module for generating strain graph of an osu!standard beatmap.",
5
5
  "keywords": [
6
6
  "osu",
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@rian8337/osu-base": "4.0.0-beta.91",
37
- "@rian8337/osu-difficulty-calculator": "4.0.0-beta.92",
38
- "@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.92",
37
+ "@rian8337/osu-difficulty-calculator": "4.0.0-beta.94",
38
+ "@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.94",
39
39
  "canvas": "^3.1.0"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public"
43
43
  },
44
- "gitHead": "102e7baf7e9179caf6b0e81cafb53d6e3a561184"
44
+ "gitHead": "ab494480e1793b60e89b1e8b56c73b7a6995ff1f"
45
45
  }