rosu_memory_lib/reader/
helpers.rs1use crate::reader::common::GameMode;
2use crate::reader::structs::Hit;
3use crate::reader::structs::State;
4use crate::Error;
5use rosu_mem::process::{Process, ProcessTraits};
6
7macro_rules! generate_reader_fn {
8 (
9 $name:ident, $ret_ty:ty, $read_fn:ident
10 ) => {
11 pub(crate) fn $name(
12 p: &Process,
13 state: &mut State,
14 offset: i32,
15 get_base_addr: fn(&Process, &mut State) -> Result<i32, Error>,
16 ) -> Result<$ret_ty, Error> {
17 let base_addr = get_base_addr(p, state)?;
18 Ok(p.$read_fn(base_addr + offset)?)
19 }
20 };
21}
22generate_reader_fn!(read_string, String, read_string);
23generate_reader_fn!(read_i16, i16, read_i16);
24generate_reader_fn!(read_i32, i32, read_i32);
25generate_reader_fn!(read_u32, u32, read_u32);
26generate_reader_fn!(read_i64, i64, read_i64);
27generate_reader_fn!(read_u64, u64, read_u64);
28generate_reader_fn!(read_f32, f32, read_f32);
29generate_reader_fn!(read_f64, f64, read_f64);
30
31#[macro_export]
32macro_rules! generate_offset_getter {
33 (
34 $( $fn_name:ident : $ret_ty:ty = $read_fn:ident ( $offset:expr , $get_base:ident ); )*
35 ) => {
36 $(
37 pub fn $fn_name(p: &Process, state: &mut State) -> Result<$ret_ty, Error> {
38 Ok(<$ret_ty>::from($read_fn(p, state, $offset, $get_base)?))
39 }
40 )*
41 };
42}
43#[macro_export]
45macro_rules! impl_osu_accessor {
46 ($(fn $name:ident() -> $ret:ty => $call:path),* $(,)?) => {
47 $(
48 pub fn $name(&mut self) -> Result<$ret, Error> {
49 match self.osu_type {
50 OsuClientKind::Stable => $call(self.process, self.state),
51 _ => Err(Error::Unsupported(
52 "Unsupported osu type for now".to_string(),
53 )),
54 }
55 }
56 )*
57 };
58}
59
60#[inline]
62pub fn calculate_accuracy(gamemode: &GameMode, hit: &Hit) -> Result<f64, Error> {
63 let acc = match gamemode {
64 GameMode::Osu => {
65 let total = (hit._300 + hit._100 + hit._50 + hit._miss) as f64;
66 if total == 0.0 {
67 return Ok(0.0);
68 }
69 let score = hit._300 as f64 * 6.0 + hit._100 as f64 * 2.0 + hit._50 as f64;
70 (score / (total * 6.0)) * 100.0
71 }
72 GameMode::Taiko => {
73 let total = (hit._300 + hit._100 + hit._50 + hit._miss) as f64;
74 if total == 0.0 {
75 return Ok(0.0);
76 }
77 let score = hit._300 as f64 * 2.0 + hit._100 as f64;
78 (score / (total * 2.0)) * 100.0
79 }
80 GameMode::Catch => {
81 let caught = (hit._300 + hit._100 + hit._50) as f64;
82 let total = (hit._300 + hit._100 + hit._50 + hit._katu + hit._miss) as f64;
83 if total == 0.0 {
84 return Ok(0.0);
85 }
86 (caught / total) * 100.0
87 }
88 GameMode::Mania => {
89 let total = (hit._geki + hit._300 + hit._katu + hit._100 + hit._50 + hit._miss) as f64;
90 if total == 0.0 {
91 return Ok(0.0);
92 }
93 let score = (hit._geki + hit._300) as f64 * 6.0
94 + hit._katu as f64 * 4.0
95 + hit._100 as f64 * 2.0
96 + hit._50 as f64;
97 (score / (total * 6.0)) * 100.0
98 }
99 _ => return Ok(0.0),
100 };
101
102 Ok(acc)
103}