Skip to content

Instantly share code, notes, and snippets.

@m13253
Last active August 18, 2026 21:55
Show Gist options
  • Select an option

  • Save m13253/4d6fbe0c369ef4b41dc8731591d86686 to your computer and use it in GitHub Desktop.

Select an option

Save m13253/4d6fbe0c369ef4b41dc8731591d86686 to your computer and use it in GitHub Desktop.
DX Rating Target Calculator
#!/usr/bin/env python3
# DX Rating Target Calculator
# Compatible to version 1.60 (CiRCLE)
import matplotlib.pyplot as plt
import numpy as np
import numpy.typing as npt
OUTPUT_PATH = "figure.png"
LEVEL_MIN = 10
LEVEL_MAX = 15
TARGET_RATINGS: list[tuple[int, str]] = [
(10000, "#5e00bb"),
(12000, "#7a1100"),
(13000, "#004a85"),
(14000, "#ba3800"),
(14500, "#6e4806"),
(15000, "#200070"),
(16000, "#000000"),
]
def adjusted_achievement(
achievement: npt.NDArray[np.float64],
) -> npt.NDArray[np.float64]:
# Reference: https://silentblue.remywiki.com/maimai_DX:Rating#Gen_3
return (
np.select(
[
(0 <= achievement) & (achievement < 50), # D
(50 <= achievement) & (achievement < 60), # C
(60 <= achievement) & (achievement < 70), # B
(70 <= achievement) & (achievement < 75), # BB
(75 <= achievement) & (achievement < 80), # BBB
(80 <= achievement) & (achievement < 90), # A
(90 <= achievement) & (achievement < 94), # AA
(94 <= achievement) & (achievement < 97), # AAA
(97 <= achievement) & (achievement < 98), # S
(98 <= achievement) & (achievement < 99), # S+
(99 <= achievement) & (achievement < 99.5), # SS
(99.5 <= achievement) & (achievement < 100), # SS+
(100 <= achievement) & (achievement < 100.5), # SSS
(100.5 <= achievement) & (achievement <= 101), # SSS+
],
[
0.050, # D
0.080, # C
0.096, # B
0.112, # BB
0.120, # BBB
0.136, # A
0.152, # AA
0.168, # AAA
0.200, # S
0.203, # S+
0.208, # SS
0.211, # SS+
0.216, # SSS
0.224, # SSS+
],
np.nan,
)
* achievement
)
def main():
ACHIEVEMENT_MIN = 93
ACHIEVEMENT_MAX = 101
NUM_SONGS = 50
achievements = np.linspace(ACHIEVEMENT_MIN, ACHIEVEMENT_MAX, 4096)
adjusted = adjusted_achievement(achievements)
denominator = 1 / (adjusted * NUM_SONGS)
plt.rcParams["font.family"] = "Helvetica Neue"
_ = plt.title("DX Rating Target Calculator")
_ = plt.xlabel("Chart level")
_ = plt.ylabel("Achievement rate (%)")
_ = plt.xticks(np.arange(LEVEL_MIN, LEVEL_MAX + 1))
_ = plt.xticks(np.arange(LEVEL_MIN, LEVEL_MAX + 0.2, 0.2), minor=True)
_ = plt.yticks([0, 50, 60, 70, 75, 80, 90, 94, 97, 98, 99, 99.5, 100, 100.5, 101])
_ = plt.yticks(np.arange(0, 101, 1), minor=True)
_ = plt.xlim(LEVEL_MIN, LEVEL_MAX)
_ = plt.ylim(94, ACHIEVEMENT_MAX)
_ = plt.grid(which="both", linewidth=0.5)
for rating, color in TARGET_RATINGS:
target_level = rating * denominator
# 0.5 offsets Math.floor
target_level[:-1] += 0.5 / adjusted[:-1]
# 101% must be All Perfect+, offsetting the 1 bonus rating for AP and AP+
target_level[-1] -= 0.5 / adjusted[-1]
_ = plt.plot(target_level, achievements, color=color, label=str(rating))
_ = plt.legend(reverse=True)
plt.savefig(OUTPUT_PATH, dpi=160, bbox_inches="tight")
print(f"Saved to {OUTPUT_PATH}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment