peace-performance (Rust) binding for python. To calculate star ratings and performance points for all osu! gamemodes

Overview

peace-performance-python

Fast, To calculate star ratings and performance points for all osu! gamemodes

peace-performance (Rust) binding for python based on PyO3.

Cross-platform support.

Faster than oppai-ng, see the benchmark for details.

Note: This library is not currently uploaded to PypI, you may need to download it locally for compilation and then import it in python.

Minimal Examples

from peace_performance_python.prelude import *

beatmap = await Beatmap.create('path_to_osu_file') # Beatmap can be cached and reused!
result = Calculator(acc=98.8, miss=3).calculate(beatmap) # Calculator can also

Full Examples

import asyncio
import sys

# import all
from peace_performance_python.prelude import *
# or
# from peace_performance_python.beatmap import Beatmap
# from peace_performance_python.calculator import Calculator

from tests import join_beatmap, HITORIGOTO


# Initial Rust logger (optional)
set_log_level('trace')
init_logger()


# Choose a style you like
def calculate_1(beatmap: Beatmap) -> CalcResult:
    return calculate_pp(beatmap, Calculator({'acc': 98.8, 'miss': 3}))


def calculate_2(beatmap: Beatmap) -> CalcResult:
    # --
    c = Calculator()
    c.set_acc(98.8)
    c.set_miss(3)

    # or
    c.acc = 98.8
    c.miss = 3

    # or
    c.setattr('acc', 98.8)
    c.setattr('miss', 3)
    return calculate_pp(beatmap, c)


def calculate_3(beatmap: Beatmap) -> CalcResult:
    c = Calculator()
    c.set_with_dict({'acc': 98.8, 'miss': 3})
    return calculate_pp(beatmap, c)


def calculate_4(beatmap: Beatmap) -> CalcResult:
    return Calculator({'acc': 98.8, 'miss': 3}).calculate(beatmap)


def calculate_5(beatmap: Beatmap) -> CalcResult:
    return Calculator(acc=98.8, miss=3).calculate(beatmap)


async def main():
    path = join_beatmap(HITORIGOTO)
    # Load beatmap
    beatmap = await Beatmap.create(path)
    # Calculate pp
    result = calculate_5(beatmap)
    print('\n***** result:', result)
    print('\n***** result.pp:', result.pp)
    print('\n***** result as dict:', result.attrs_dict)
    print('\n***** result.raw_stars as dict:', result.raw_stars.attrs_dict)
    print('\n***** result.raw_pp as dict:', result.raw_pp.attrs_dict)

if __name__ == '__main__':
    asyncio.run(main())

Running results

 TRACE peace_performance_python::methods::common > function=async_read_file duration=289.1µs
 TRACE peace_performance_python::methods::pp     > function=async_parse_beatmap duration=414µs
 TRACE peace_performance_python::methods::pp     > function=calc_with_any_pp duration=99.6µs
 TRACE peace_performance_python::objects::calculator > function=calc duration=245.4µs

...

***** result.pp: 152.19204711914062

...

***** result as dict: {
    'mode': 0, 
    'mods': 0, 
    'pp': 152.19204711914062, 
    'stars': 5.162832260131836, 
    'raw_pp': {
        'aim': 73.0337905883789, 
        'spd': 31.048368453979492, 
        'str': None, 
        'acc': 45.17241287231445, 
        'total': 152.19204711914062}, 
    'raw_stars': {
        'stars': 5.162832260131836, 
        'max_combo': 476, 
        'ar': 9.0, 
        'n_fruits': None, 
        'n_droplets': None, 
        'n_tiny_droplets': None, 
        'od': 8.5, 
        'speed_strain': 2.0723509788513184, 
        'aim_strain': 2.7511043548583984, 
        'n_circles': 207, 
        'n_spinners': 1
        }
    }

...

Building

This package is intended to be built using rust, maturin or setuptools_rust.

1. Install Rust

posix

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

windows

https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe

2. Install python dev dependencies

pip install -r requirements-dev.txt

3. Build native python lib

maturin develop --release

OR

python setup.py develop

Compile to .whl to use pip installation

maturin build --release

OR

python setup.py bdist_wheel

install .whl

# maturin build
pip install target/wheels/<name>.whl

# setup.py build
pip install dist/<name>.whl

Run tests and benchmarks

Once built, you can run the tests and benchmakrs using pytest

pytest

or bench and draw a image

pytest --benchmark-histogram

Run examples

python examples.py

Vs Oppai-ng

peace-performance Python bindings vs C89 oppai-ng.

Fast than oppai, the longer the map, the more obvious the advantages of rust.

peace-performance enables the no_sliders_no_leniency feature to be consistent with oppai's algorithm (faster, but loses precision).

If you need maximum precision (osu-performance) rather than performance, use all_included features.

------------------------------------------------------------------------ benchmark 'bench-oppai-vs-rust': 12 tests -------------------------------------------------------------------------
Name (time in ms)               Min                Max               Mean            StdDev             Median               IQR            Outliers       OPS            Rounds  Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_rust_padoru             1.7768 (1.0)       1.9478 (1.0)       1.8508 (1.0)      0.0400 (1.0)       1.8443 (1.0)      0.0535 (1.0)          28;0  540.3156 (1.0)          87           1
test_oppai_padoru            1.8122 (1.02)      9.7861 (5.02)      1.9889 (1.07)     0.5237 (13.08)     1.9249 (1.04)     0.1314 (2.46)          7;8  502.7874 (0.93)        242           1
test_rust_hitorigoto         2.0610 (1.16)      2.5040 (1.29)      2.1910 (1.18)     0.0657 (1.64)      2.1785 (1.18)     0.0694 (1.30)        95;19  456.4104 (0.84)        418           1
test_oppai_hitorigoto        2.5288 (1.42)      3.7520 (1.93)      2.7401 (1.48)     0.1818 (4.54)      2.7067 (1.47)     0.1176 (2.20)        25;17  364.9477 (0.68)        322           1
test_rust_freedom_dive       3.8093 (2.14)      7.3134 (3.75)      3.9828 (2.15)     0.2293 (5.73)      3.9567 (2.15)     0.0845 (1.58)          4;6  251.0782 (0.46)        241           1
test_rust_sotarks            4.4968 (2.53)      5.1071 (2.62)      4.6848 (2.53)     0.0985 (2.46)      4.6712 (2.53)     0.0965 (1.80)        45;13  213.4562 (0.40)        196           1
test_oppai_freedom_dive      5.6872 (3.20)      7.0520 (3.62)      5.9250 (3.20)     0.2010 (5.02)      5.8822 (3.19)     0.1848 (3.46)         17;7  168.7767 (0.31)        159           1
test_oppai_sotarks           6.1222 (3.45)     16.0620 (8.25)      6.4435 (3.48)     0.8114 (20.27)     6.3351 (3.43)     0.1677 (3.14)         3;10  155.1956 (0.29)        152           1
test_rust_galaxy_burst       6.1535 (3.46)      7.3282 (3.76)      6.4249 (3.47)     0.1903 (4.75)      6.3857 (3.46)     0.1377 (2.57)        21;10  155.6452 (0.29)        148           1
test_oppai_galaxy_burst      8.1627 (4.59)     11.3769 (5.84)      8.5283 (4.61)     0.3584 (8.96)      8.4481 (4.58)     0.2359 (4.41)          9;6  117.2565 (0.22)        110           1
test_rust_unforgiving       12.9719 (7.30)     13.9540 (7.16)     13.2572 (7.16)     0.1567 (3.92)     13.2482 (7.18)     0.1395 (2.61)         16;4   75.4307 (0.14)         71           1
test_oppai_unforgiving      22.4598 (12.64)    35.3505 (18.15)    23.6072 (12.76)    2.4802 (61.97)    22.8837 (12.41)    0.4452 (8.32)          3;4   42.3600 (0.08)         44           1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Simple Benchmarks

Native vs wrapped beatmap object

Read and parsing time spent on beatmap of different sizes (forgiving is a beatmap over 50 minutes long and takes the longest)

There are also subtle differences in the different calling methods


MIT

pure-peace

You might also like...
Script to calculate delegator epoch returns for all pillars

znn_delegator_calculator Script to calculate estimated delegator epoch returns for all Pillars, so you can delegate to the best one. You can find me o

A weekly dive into commonly used modules in the Rust ecosystem, with story flavor!

The goal of this project is to bring the same concept as PyMOTW to the Rust world. PyMOTW was an invaluable resource for me when I was learning Python years ago, and I hope that I can help someone in a similar way. Each week we'll dive into a module and explore some of the functionality that we can find there while following along the adventures of some colourful characters.

A tool to assist in code raiding in rust
A tool to assist in code raiding in rust

Kodelock a tool to assist in code raiding in rust This tool is designed to be used on a second monitor. This tools will allow you to see a easily read

PyWorkflow(PyWF) - A Python Binding of C++ Workflow

PyWorkflow(PyWF) - A Python Binding of C++ Workflow 概览 C++ Workflow是一个高性能的异步引擎,本项目着力于实现一个Python版的Workflow,让Python用户也能享受Workflow带来的绝佳体验。

jmespath.rs Python binding

rjmespath-py jmespath.rs Python binding.

Tindicators is a Python library to calculate the values of various technical indicators

Tindicators is a Python library to calculate the values of various technical indicators

Flames Calculater App used to calculate flames status between two names created using python's Flask web framework.
Flames Calculater App used to calculate flames status between two names created using python's Flask web framework.

Flames Finder Web App Flames Calculater App used to calculate flames status between two names created using python's Flask web framework. First, App g

A program to calculate the are of a triangle. made with Python.
A program to calculate the are of a triangle. made with Python.

Area-Calculator What is Area-Calculator? Area-Calculator is a program to find out the area of a triangle easily. fully made with Python. Needed a pyth

Comments
  • configuration error: `project.license` must be valid exactly by one definition (2 matches found):

    configuration error: `project.license` must be valid exactly by one definition (2 matches found):

    Hi ! By installing the package to install bancho.py, I've encountered a problem with the pkg.

    Collecting peace-performance-python==1.1.2
      Downloading peace-performance-python-1.1.2.tar.gz (25 kB)
      Installing build dependencies ... done
      Getting requirements to build wheel ... error
      error: subprocess-exited-with-error
      
      × Getting requirements to build wheel did not run successfully.
      │ exit code: 1
      ╰─> [80 lines of output]
          configuration error: `project.license` must be valid exactly by one definition (2 matches found):
          
              - keys:
                  'file': {type: string}
                required: ['file']
              - keys:
                  'text': {type: string}
                required: ['text']
          
          DESCRIPTION:
              `Project license <https://www.python.org/dev/peps/pep-0621/#license>`_.
          
          GIVEN VALUE:
              "MIT"
          
          OFFENDING RULE: 'oneOf'
          
          DEFINITION:
              {
                  "oneOf": [
                      {
                          "properties": {
                              "file": {
                                  "type": "string",
                                  "$$description": [
                                      "Relative path to the file (UTF-8) which contains the license for the",
                                      "project."
                                  ]
                              }
                          },
                          "required": [
                              "file"
                          ]
                      },
                      {
                          "properties": {
                              "text": {
                                  "type": "string",
                                  "$$description": [
                                      "The license of the project whose meaning is that of the",
                                      "`License field from the core metadata",
                                      "<https://packaging.python.org/specifications/core-metadata/#license>`_."
                                  ]
                              }
                          },
                          "required": [
                              "text"
                          ]
                      }
                  ]
              }
          Traceback (most recent call last):
            File "/usr/local/lib/python3.9/dist-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
              main()
            File "/usr/local/lib/python3.9/dist-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
              json_out['return_val'] = hook(**hook_input['kwargs'])
            File "/usr/local/lib/python3.9/dist-packages/pip/_vendor/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
              return hook(config_settings)
            File "/usr/local/lib/python3.9/dist-packages/setuptools/build_meta.py", line 177, in get_requires_for_build_wheel
              return self._get_build_requires(
            File "/usr/local/lib/python3.9/dist-packages/setuptools/build_meta.py", line 159, in _get_build_requires
              self.run_setup()
            File "/usr/local/lib/python3.9/dist-packages/setuptools/build_meta.py", line 281, in run_setup
              super(_BuildMetaLegacyBackend,
            File "/usr/local/lib/python3.9/dist-packages/setuptools/build_meta.py", line 174, in run_setup
              exec(code, locals())
            File "<string>", line 20, in <module>
            File "/usr/local/lib/python3.9/dist-packages/setuptools/__init__.py", line 87, in setup
              return distutils.core.setup(**attrs)
            File "/usr/local/lib/python3.9/dist-packages/setuptools/_distutils/core.py", line 151, in setup
              dist.parse_config_files()
            File "/usr/local/lib/python3.9/dist-packages/setuptools/dist.py", line 868, in parse_config_files
              pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
            File "/usr/local/lib/python3.9/dist-packages/setuptools/config/pyprojecttoml.py", line 58, in apply_configuration
              config = read_configuration(filepath, True, ignore_option_errors, dist)
            File "/usr/local/lib/python3.9/dist-packages/setuptools/config/pyprojecttoml.py", line 122, in read_configuration
              validate(subset, filepath)
            File "/usr/local/lib/python3.9/dist-packages/setuptools/config/pyprojecttoml.py", line 47, in validate
              raise error from None
          ValueError: invalid pyproject.toml config: `project.license`
          [end of output]
      
      note: This error originates from a subprocess, and is likely not a problem with pip.
    error: subprocess-exited-with-error
    
    × Getting requirements to build wheel did not run successfully.
    │ exit code: 1
    ╰─> See above for output.
    
    note: This error originates from a subprocess, and is likely not a problem with pip.
    

    Got this error on a clean install (Ubuntu 22) & by following the steps of bancho.py installation. I didn't have this problem on x86 but since I moved to an aarch64 (ARM), it happened.

    opened by Lxmune 1
Releases(release-v2.0.0)
Owner
纯和平
null
Python binding to rust zw-fast-quantile

zw_fast_quantile_py zw-fast-quantile python binding Installation pip install zw_fast_quantile_py Usage import zw_fast_quantile_py

Paul Meng 1 Dec 30, 2021
A tool to allow New World players to calculate the best place to put their Attribute Points for their build and level

New World Damage Simulator A tool designed to take a characters base stats including armor and weapons, level, and base damage of their items (slash d

Joseph P Langford 31 Nov 1, 2022
The docker-based Open edX distribution designed for peace of mind

Tutor: the docker-based Open edX distribution designed for peace of mind Tutor is a docker-based Open edX distribution, both for production and local

Overhang.IO 696 Dec 31, 2022
A tool to replace all osu beatmap backgrounds at once.

OsuBgTool A tool to replace all osu beatmap backgrounds at once. Requirements You need to have python 3.6 or newer installed. That's it. How to Use Ju

Aditya Gupta 1 Oct 24, 2021
Anki Addon idea by gbrl.sc to see previous ratings of a card in the reviewer

Card History At A Glance Stop having to press card browser and ctrl+i for every card and then WINCING to see it's history of reviews FEATURES Visualiz

Jerry Zhou 11 Dec 19, 2022
An osu! cheat made in c++ rewritten in python and currently undetected.

megumi-python An osu! cheat made in c++ rewritten in python and currently undetected. Installation Guide Download python 3.9 from https://python.org C

Elaina 2 Nov 18, 2022
A python script for osu!lazer rulesets auto update.

osu-lazer-rulesets-autoupdater A python script for osu!lazer rulesets auto update. How to use: 如何使用: You can refer to the python script. The begining

null 3 Jul 26, 2022
Data 25 Star Wars Project With Python

Data 25 Star Wars Project Instructions The character data in your MongoDB database has been pulled from https://swapi.tech/. As well as 'people', the

null 1 Dec 24, 2021
Osu statistics right on your desktop, made with pyqt

Osu!Stat Osu statistics right on your desktop, made with Qt5 Credits Would like to thank these creators for their projects and contributions. ppy, osu

Aditya Gupta 21 Jul 13, 2022
Github Star Tracking app with Streamlit

github-star-tracking-python-app Github Star Tracking app with Streamlit #8daysofstreamlit How to run it locally? Clone or Download & Unzip the Repo En

amrrs 4 Sep 22, 2022