UNPKG

rg-stats

Version:

A library for calculating various rhythm game stats.

338 lines (324 loc) 7.01 kB
import t from "tap"; import { isAprx } from "../test-utils/approx"; import { TestCase } from "../test-utils/test-case"; import { ThrowsToSnapshot } from "../test-utils/throw-snapshot"; import { calculate, inverse } from "./jubility"; const testCases = [ [80, 10.9, 110.1], [85, 10.9, 116.9], [90, 10.9, 123.8], [95, 10.9, 130.7], [100, 10.9, 137.6], [105, 10.9, 144.5], [110, 10.9, 151.3], [115, 10.9, 158.2], [120, 10.9, 165.1], [80, 10.8, 109.0], [85, 10.8, 115.9], [90, 10.8, 122.7], [95, 10.8, 129.5], [100, 10.8, 136.3], [105, 10.8, 143.1], [110, 10.8, 150.0], [115, 10.8, 156.8], [120, 10.8, 163.6], [80, 10.7, 108.0], [85, 10.7, 114.8], [90, 10.7, 121.5], [95, 10.7, 128.3], [100, 10.7, 135.1], [105, 10.7, 141.8], [110, 10.7, 148.6], [115, 10.7, 155.3], [120, 10.7, 162.1], [80, 10.6, 107.0], [85, 10.6, 113.7], [90, 10.6, 120.4], [95, 10.6, 127.1], [100, 10.6, 133.8], [105, 10.6, 140.5], [110, 10.6, 147.2], [115, 10.6, 153.9], [120, 10.6, 160.6], [80, 10.5, 106.0], [85, 10.5, 112.6], [90, 10.5, 119.3], [95, 10.5, 125.9], [100, 10.5, 132.5], [105, 10.5, 139.2], [110, 10.5, 145.8], [115, 10.5, 152.4], [120, 10.5, 159.0], [80, 10.4, 105.0], [85, 10.4, 111.6], [90, 10.4, 118.1], [95, 10.4, 124.7], [100, 10.4, 131.3], [105, 10.4, 137.8], [110, 10.4, 144.4], [115, 10.4, 151.0], [120, 10.4, 157.5], [80, 10.3, 104.0], [85, 10.3, 110.5], [90, 10.3, 117.0], [95, 10.3, 123.5], [100, 10.3, 130.0], [105, 10.3, 136.5], [110, 10.3, 143.0], [115, 10.3, 149.5], [120, 10.3, 156.0], [80, 10.2, 103.0], [85, 10.2, 109.4], [90, 10.2, 115.9], [95, 10.2, 122.3], [100, 10.2, 128.7], [105, 10.2, 135.2], [110, 10.2, 141.6], [115, 10.2, 148.1], [120, 10.2, 154.5], [80, 10.1, 102.0], [85, 10.1, 108.3], [90, 10.1, 114.7], [95, 10.1, 121.1], [100, 10.1, 127.5], [105, 10.1, 133.9], [110, 10.1, 140.2], [115, 10.1, 146.6], [120, 10.1, 153.0], [80, 10.0, 101.0], [85, 10.0, 107.3], [90, 10.0, 113.6], [95, 10.0, 119.9], [100, 10.0, 126.2], [105, 10.0, 132.5], [110, 10.0, 138.8], [115, 10.0, 145.2], [120, 10.0, 151.5], [80, 9.9, 100.0], [85, 9.9, 106.2], [90, 9.9, 112.5], [95, 9.9, 118.7], [100, 9.9, 125.0], [105, 9.9, 131.2], [110, 9.9, 137.5], [115, 9.9, 143.7], [120, 9.9, 150.0], [80, 9.8, 98.9], [85, 9.8, 105.1], [90, 9.8, 111.3], [95, 9.8, 117.5], [100, 9.8, 123.7], [105, 9.8, 129.9], [110, 9.8, 136.1], [115, 9.8, 142.2], [120, 9.8, 148.4], [80, 9.7, 97.9], [85, 9.7, 104.1], [90, 9.7, 110.2], [95, 9.7, 116.3], [100, 9.7, 122.4], [105, 9.7, 128.5], [110, 9.7, 134.7], [115, 9.7, 140.8], [120, 9.7, 146.9], [80, 9.6, 96.9], [85, 9.6, 103.0], [90, 9.6, 109.0], [95, 9.6, 115.1], [100, 9.6, 121.2], [105, 9.6, 127.2], [110, 9.6, 133.3], [115, 9.6, 139.3], [120, 9.6, 145.4], [80, 9.5, 95.9], [85, 9.5, 101.9], [90, 9.5, 107.9], [95, 9.5, 113.9], [100, 9.5, 119.9], [105, 9.5, 125.9], [110, 9.5, 131.9], [115, 9.5, 137.9], [120, 9.5, 143.9], [80, 9.4, 94.9], [85, 9.4, 100.8], [90, 9.4, 106.8], [95, 9.4, 112.7], [100, 9.4, 118.6], [105, 9.4, 124.6], [110, 9.4, 130.5], [115, 9.4, 136.4], [120, 9.4, 142.4], [80, 9.3, 93.9], [85, 9.3, 99.8], [90, 9.3, 105.6], [95, 9.3, 111.5], [100, 9.3, 117.4], [105, 9.3, 123.2], [110, 9.3, 129.1], [115, 9.3, 135.0], [120, 9.3, 140.9], [80, 9.2, 92.9], [85, 9.2, 98.7], [90, 9.2, 104.5], [95, 9.2, 110.3], [100, 9.2, 116.1], [105, 9.2, 121.9], [110, 9.2, 127.7], [115, 9.2, 133.5], [120, 9.2, 139.3], [80, 9.1, 91.9], [85, 9.1, 97.6], [90, 9.1, 103.4], [95, 9.1, 109.1], [100, 9.1, 114.8], [105, 9.1, 120.6], [110, 9.1, 126.3], [115, 9.1, 132.1], [120, 9.1, 137.8], [80, 9.0, 90.9], [85, 9.0, 96.5], [90, 9.0, 102.2], [95, 9.0, 107.9], [100, 9.0, 113.6], [105, 9.0, 119.3], [110, 9.0, 125.0], [115, 9.0, 130.6], [120, 9.0, 136.3], [80, 8, 80.8], [85, 8, 85.8], [90, 8, 90.9], [95, 8, 95.9], [100, 8, 101.0], [105, 8, 106.0], [110, 8, 111.1], [115, 8, 116.1], [120, 8, 121.2], [80, 7, 70.7], [85, 7, 75.1], [90, 7, 79.5], [95, 7, 83.9], [100, 7, 88.3], [105, 7, 92.8], [110, 7, 97.2], [115, 7, 101.6], [120, 7, 106.0], [80, 6, 60.6], [85, 6, 64.3], [90, 6, 68.1], [95, 6, 71.9], [100, 6, 75.7], [105, 6, 79.5], [110, 6, 83.3], [115, 6, 87.1], [120, 6, 90.9], [80, 5, 50.5], [85, 5, 53.6], [90, 5, 56.8], [95, 5, 59.9], [100, 5, 63.1], [105, 5, 66.2], [110, 5, 69.4], [115, 5, 72.6], [120, 5, 75.7], [80, 4, 40.4], [85, 4, 42.9], [90, 4, 45.4], [95, 4, 47.9], [100, 4, 50.5], [105, 4, 53.0], [110, 4, 55.5], [115, 4, 58.0], [120, 4, 60.6], [80, 3, 30.3], [85, 3, 32.1], [90, 3, 34.0], [95, 3, 35.9], [100, 3, 37.8], [105, 3, 39.7], [110, 3, 41.6], [115, 3, 43.5], [120, 3, 45.4], [80, 2, 20.2], [85, 2, 21.4], [90, 2, 22.7], [95, 2, 23.9], [100, 2, 25.2], [105, 2, 26.5], [110, 2, 27.7], [115, 2, 29.0], [120, 2, 30.3], [80, 1, 10.1], [85, 1, 10.7], [90, 1, 11.3], [95, 1, 11.9], [100, 1, 12.6], [105, 1, 13.2], [110, 1, 13.8], [115, 1, 14.5], [120, 1, 15.1], ]; t.test("Jubility Tests", (t) => { function MakeTestCase(rate: number, level: number, jubility: number): TestCase { return (t) => t.equal( // note: score doesn't actually matter, it's just there to check // that your score isn't < 700k. calculate(700_001, rate, level), jubility, `${rate}% on a level ${level} chart should be worth ${jubility} jubility.` ); } // This is just one big table stolen from bemaniwiki. for (const testCase of testCases) { MakeTestCase(testCase[0], testCase[1], testCase[2])(t); } t.equal(calculate(699_999, 100, 10), 0, "Should return 0 for scores < 700k no matter what."); t.end(); }); t.test("Jubility Validation Tests", (t) => { ThrowsToSnapshot( t, () => calculate(1_000_001, 100, 10.5), "Should throw if score is > 1million." ); ThrowsToSnapshot( t, () => calculate(1_000_000, 120.1, 10.5), "Should throw if music rate is > 120." ); ThrowsToSnapshot(t, () => calculate(-1, 100, 10.5), "Should throw if score is negative."); ThrowsToSnapshot( t, () => calculate(1_000_000, -1, 10.5), "Should throw if music rate is negative." ); ThrowsToSnapshot( t, () => calculate(1_000_000, -1, -1), "Should throw if chart level is negative." ); t.end(); }); t.test("Inverse Jubility Tests", (t) => { function MakeTestCase(rate: number, level: number, jubility: number): TestCase { return (t) => isAprx( t, // We ceil this because the bemaniwiki test dataset is not very // accurate. All our data should be pretty close, though. Math.ceil(inverse(jubility, level)), rate, `Inverse ${jubility} on a level ${level} chart should be equal to ${rate} music rate.`, 1 ); } for (const testCase of testCases) { MakeTestCase(testCase[0], testCase[1], testCase[2])(t); } ThrowsToSnapshot( t, () => inverse(9000, 1), "Should throw if the requested jubility is not possible on a chart of that level." ); t.end(); });