Source code for slider.mod

from collections import namedtuple

from .bit_enum import BitEnum


[docs]class Mod(BitEnum): """The mods in osu! """ no_fail = 1 easy = 1 << 1 no_video = 1 << 2 # not a mod anymore hidden = 1 << 3 hard_rock = 1 << 4 sudden_death = 1 << 5 double_time = 1 << 6 relax = 1 << 7 half_time = 1 << 8 nightcore = 1 << 9 # always used with double_time flashlight = 1 << 10 autoplay = 1 << 11 spun_out = 1 << 12 relax2 = 1 << 13 # same as autopilot auto_pilot = 1 << 13 # same as relax2 perfect = 1 << 14 key4 = 1 << 15 key5 = 1 << 16 key6 = 1 << 17 key7 = 1 << 18 key8 = 1 << 19 fade_in = 1 << 20 random = 1 << 21 last_mod = 1 << 22 # same as cinema cinema = 1 << 22 # same as last_mod target_practice = 1 << 23 key9 = 1 << 24 coop = 1 << 25 key1 = 1 << 26 key3 = 1 << 27 key2 = 1 << 28 scoreV2 = 1 << 29 @classmethod
[docs] def parse(cls, cs): """Parse a mod mask out of a list of shortened mod names. Parameters ---------- cs : str The mod string. Returns ------- mod_mask : int The mod mask. """ if len(cs) % 2 != 0: raise ValueError(f'malformed mods: {cs!r}') cs = cs.lower() mapping = { 'ez': cls.easy, 'hr': cls.hard_rock, 'ht': cls.half_time, 'dt': cls.double_time, 'hd': cls.hidden, 'fl': cls.flashlight, 'so': cls.spun_out, 'nf': cls.no_fail, } mod = 0 for n in range(0, len(cs), 2): try: mod |= mapping[cs[n:n + 2]] except KeyError: raise ValueError(f'unknown mod: {cs[n:n + 2]!r}') return mod
[docs]def ar_to_ms(ar): """Convert an approach rate value to milliseconds of time that an element appears on the screen before being hit. Parameters ---------- ar : float The approach rate. Returns ------- milliseconds : float The number of milliseconds that an element appears on the screen before being hit at the given approach rate. See Also -------- :func:`slider.mod.ms_to_ar` """ # NOTE: The formula for ar_to_ms is different for ar >= 5 and ar < 5 # see: https://osu.ppy.sh/wiki/Song_Setup#Approach_Rate if ar >= 5: return 1950 - (ar * 150) else: return 1800 - (ar * 120)
[docs]def ms_to_ar(ms): """Convert milliseconds to hit an element into an approach rate value. Parameters ---------- ms : float The number of milliseconds that an element appears on the screen before being hit. Returns ------- ar : float The approach rate value that produces the given millisecond value. See Also -------- :func:`slider.mod.ar_to_ms` """ # NOTE: The formula for ar_to_ms is different for ar >= 5 and ar < 5 # see: https://osu.ppy.sh/wiki/Song_Setup#Approach_Rate ar = (ms - 1950) / -150 if ar < 5: # the ar lines cross at 5 but we use a different formula for the slower # approach rates. return (ms - 1800) / -120 return ar
[docs]def circle_radius(cs): """Compute the ``CS`` attribute into a circle radius in osu! pixels. Parameters ---------- cs : float The circle size. Returns ------- radius : float The radius in osu! pixels. """ return (512 / 16) * (1 - 0.7 * (cs - 5) / 5)
class HitWindows(namedtuple('HitWindows', 'hit_300, hit_100, hit_50')): """Times to hit an object at various accuracies Parameters ---------- hit_300 : int The maxumium number of milliseconds away from exactly on time a hit can be to still be a 300 hit_100 : int The maxumium number of milliseconds away from exactly on time a hit can be to still be a 100 hit_50 : int The maxumium number of milliseconds away from exactly on time a hit can be to still be a 50 Notes ----- A hit further than the ``hit_50`` value away from the time of a hit object is a miss. """ def od_to_ms(od): """Convert an overall difficulty value into milliseconds to hit an object at various accuracies. Parameters ---------- od : float The overall difficulty. Returns ------- hw : HitWindows A namedtuple of numbers of milliseconds to hit an object at different accuracies. """ return HitWindows( hit_300=(159 - 12 * od) / 2, hit_100=(279 - 16 * od) / 2, hit_50=(399 - 20 * od) / 2, ) def od_to_ms_300(od): """Convert an overall difficulty value into milliseconds to hit an object at maximum accuracy. Parameters ---------- od : float The overall difficulty. Returns ------- ms : float The number of milliseconds to hit an object at maximum accuracy. See Also -------- :func:`slider.mod.ms_300_to_od` """ return 79.5 - 6 * od def ms_300_to_od(ms): """Convert the milliseconds to score a 300 into an OD value. Parameters ---------- ms : float The length of the 300 window in milliseconds. Returns ------- od : float The OD value that produces a 300 window of length ``ms``. See Also -------- :func:`slider.mod.od_to_ms_300` """ return (ms - 79.5) / -6