scaleSampleRates.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. interface ScalingItem {
  2. count: number;
  3. sampleRate: number;
  4. }
  5. /**
  6. * Scales the sample rates of items proportionally to their current sample rate.
  7. */
  8. export function scaleSampleRates<T extends ScalingItem>({
  9. items,
  10. sampleRate,
  11. }: {
  12. items: T[];
  13. sampleRate: number;
  14. }): {
  15. scaledItems: T[];
  16. } {
  17. const totalSpans = items.reduce((acc, item) => acc + item.count, 0);
  18. const oldSampleRate = items.reduce(
  19. (acc, item) => acc + item.sampleRate * (item.count / totalSpans),
  20. 0
  21. );
  22. if (sampleRate === oldSampleRate) {
  23. return {scaledItems: items};
  24. }
  25. if (
  26. oldSampleRate === 0 ||
  27. oldSampleRate === 1 ||
  28. sampleRate === 0 ||
  29. sampleRate === 1
  30. ) {
  31. return {
  32. scaledItems: items.map(item => ({
  33. ...item,
  34. sampleRate,
  35. })),
  36. };
  37. }
  38. const newSampled = totalSpans * sampleRate;
  39. let factor = sampleRate / oldSampleRate;
  40. let remainingTotal = totalSpans;
  41. let remainingSampleCount = newSampled;
  42. let remainingOldSampleCount = totalSpans * oldSampleRate;
  43. const sortedItems = items.toSorted((a, b) => a.count - b.count);
  44. const scaledItems: T[] = [];
  45. for (const item of sortedItems) {
  46. const newProjectRate = Math.min(1, Math.max(0, item.sampleRate * factor));
  47. const newProjectSampleCount = item.count * newProjectRate;
  48. remainingTotal -= item.count;
  49. remainingSampleCount -= newProjectSampleCount;
  50. remainingOldSampleCount -= item.count * item.sampleRate;
  51. const newTargetRate = remainingSampleCount / remainingTotal;
  52. const remainingTotalRef = remainingTotal;
  53. const remainingOldSampleRate = remainingOldSampleCount / remainingTotalRef;
  54. factor = newTargetRate / remainingOldSampleRate;
  55. scaledItems.push({
  56. ...item,
  57. sampleRate: newProjectRate,
  58. });
  59. }
  60. return {scaledItems};
  61. }