diff --git a/Cargo.toml b/Cargo.toml index ef920ac..f030283 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,3 @@ edition = "2024" num-integer = "0.1" rust_decimal = "1" rust_decimal_macros = "1" - -[features] -default = ["lookup", "fractions_simplify"] -# Use lookup tables first for conversion, then fallback to regular computations -# Noe: When using lookup tables feature, conversion from 1.67 or -150 gives 4/6 instead of 2/3 (see README.md) -lookup = [] -# Use more complex algorithm when converting to fractional. (1.33 gives 1/3 instead of 33/100) -# Note that disabling it but leaving lookup enabled will still return 1/3 from the lookup tables (see README.md) -fractions_simplify = [] diff --git a/src/Odds Ladder.json b/src/Odds Ladder.json new file mode 100644 index 0000000..9d48281 --- /dev/null +++ b/src/Odds Ladder.json @@ -0,0 +1 @@ +"horseracing":{"key":"horseracing","steps":[{"price":{"decimal":1.0010,"fractional":"1/1000"},"enabled":true},{"price":{"decimal":1.0013,"fractional":"1/750"},"enabled":true},{"price":{"decimal":1.0020,"fractional":"1/500"},"enabled":true},{"price":{"decimal":1.0025,"fractional":"1/400"},"enabled":true},{"price":{"decimal":1.0030,"fractional":"1/300"},"enabled":true},{"price":{"decimal":1.0040,"fractional":"1/250"},"enabled":true},{"price":{"decimal":1.0050,"fractional":"1/200"},"enabled":true},{"price":{"decimal":1.0070,"fractional":"1/150"},"enabled":true},{"price":{"decimal":1.0100,"fractional":"1/100"},"enabled":true},{"price":{"decimal":1.0120,"fractional":"1/80"},"enabled":true},{"price":{"decimal":1.0150,"fractional":"1/66"},"enabled":true},{"price":{"decimal":1.0200,"fractional":"1/50"},"enabled":true},{"price":{"decimal":1.0250,"fractional":"1/40"},"enabled":true},{"price":{"decimal":1.0300,"fractional":"1/33"},"enabled":true},{"price":{"decimal":1.0400,"fractional":"1/25"},"enabled":true},{"price":{"decimal":1.0500,"fractional":"1/20"},"enabled":true},{"price":{"decimal":1.0550,"fractional":"1/18"},"enabled":true},{"price":{"decimal":1.0600,"fractional":"1/16"},"enabled":true},{"price":{"decimal":1.0700,"fractional":"1/14"},"enabled":true},{"price":{"decimal":1.0800,"fractional":"1/12"},"enabled":true},{"price":{"decimal":1.0900,"fractional":"1/11"},"enabled":true},{"price":{"decimal":1.1000,"fractional":"1/10"},"enabled":true},{"price":{"decimal":1.1100,"fractional":"1/9"},"enabled":true},{"price":{"decimal":1.1200,"fractional":"1/8"},"enabled":true},{"price":{"decimal":1.1300,"fractional":"2/15"},"enabled":true},{"price":{"decimal":1.1400,"fractional":"1/7"},"enabled":true},{"price":{"decimal":1.1500,"fractional":"2/13"},"enabled":true},{"price":{"decimal":1.1600,"fractional":"1/6"},"enabled":true},{"price":{"decimal":1.1800,"fractional":"2/11"},"enabled":true},{"price":{"decimal":1.1900,"fractional":"19/100"},"enabled":false},{"price":{"decimal":1.2000,"fractional":"1/5"},"enabled":true},{"price":{"decimal":1.2100,"fractional":"21/100"},"enabled":false},{"price":{"decimal":1.2200,"fractional":"2/9"},"enabled":true},{"price":{"decimal":1.2300,"fractional":"23/100"},"enabled":false},{"price":{"decimal":1.2400,"fractional":"6/25"},"enabled":false},{"price":{"decimal":1.2500,"fractional":"1/4"},"enabled":true},{"price":{"decimal":1.2600,"fractional":"13/50"},"enabled":false},{"price":{"decimal":1.2700,"fractional":"27/100"},"enabled":false},{"price":{"decimal":1.2900,"fractional":"2/7"},"enabled":true},{"price":{"decimal":1.3000,"fractional":"3/10"},"enabled":true},{"price":{"decimal":1.3100,"fractional":"31/100"},"enabled":false},{"price":{"decimal":1.3200,"fractional":"8/25"},"enabled":false},{"price":{"decimal":1.3300,"fractional":"1/3"},"enabled":true},{"price":{"decimal":1.3400,"fractional":"17/50"},"enabled":false},{"price":{"decimal":1.3500,"fractional":"7/20"},"enabled":false},{"price":{"decimal":1.3600,"fractional":"4/11"},"enabled":true},{"price":{"decimal":1.3700,"fractional":"37/100"},"enabled":false},{"price":{"decimal":1.3800,"fractional":"19/50"},"enabled":false},{"price":{"decimal":1.3900,"fractional":"39/100"},"enabled":false},{"price":{"decimal":1.4000,"fractional":"2/5"},"enabled":true},{"price":{"decimal":1.4100,"fractional":"41/100"},"enabled":false},{"price":{"decimal":1.4200,"fractional":"21/50"},"enabled":false},{"price":{"decimal":1.4300,"fractional":"43/100"},"enabled":false},{"price":{"decimal":1.4400,"fractional":"4/9"},"enabled":true},{"price":{"decimal":1.4500,"fractional":"9/20"},"enabled":false},{"price":{"decimal":1.4600,"fractional":"23/50"},"enabled":false},{"price":{"decimal":1.4700,"fractional":"40/85"},"enabled":true},{"price":{"decimal":1.4800,"fractional":"12/25"},"enabled":false},{"price":{"decimal":1.4900,"fractional":"49/100"},"enabled":false},{"price":{"decimal":1.5000,"fractional":"1/2"},"enabled":true},{"price":{"decimal":1.5100,"fractional":"51/100"},"enabled":false},{"price":{"decimal":1.5200,"fractional":"13/25"},"enabled":false},{"price":{"decimal":1.5300,"fractional":"8/15"},"enabled":true},{"price":{"decimal":1.5400,"fractional":"27/50"},"enabled":false},{"price":{"decimal":1.5500,"fractional":"11/20"},"enabled":false},{"price":{"decimal":1.5600,"fractional":"14/25"},"enabled":false},{"price":{"decimal":1.5700,"fractional":"4/7"},"enabled":true},{"price":{"decimal":1.5800,"fractional":"29/50"},"enabled":false},{"price":{"decimal":1.5900,"fractional":"59/100"},"enabled":false},{"price":{"decimal":1.6000,"fractional":"3/5"},"enabled":false},{"price":{"decimal":1.6100,"fractional":"8/13"},"enabled":true},{"price":{"decimal":1.6300,"fractional":"63/100"},"enabled":false},{"price":{"decimal":1.6400,"fractional":"16/25"},"enabled":false},{"price":{"decimal":1.6500,"fractional":"13/20"},"enabled":false},{"price":{"decimal":1.6600,"fractional":"4/6"},"enabled":true},{"price":{"decimal":1.6800,"fractional":"34/50"},"enabled":false},{"price":{"decimal":1.6900,"fractional":"69/100"},"enabled":true},{"price":{"decimal":1.7000,"fractional":"7/10"},"enabled":false},{"price":{"decimal":1.7100,"fractional":"71/100"},"enabled":false},{"price":{"decimal":1.7200,"fractional":"8/11"},"enabled":true},{"price":{"decimal":1.7400,"fractional":"37/50"},"enabled":false},{"price":{"decimal":1.7500,"fractional":"3/4"},"enabled":true},{"price":{"decimal":1.7600,"fractional":"19/25"},"enabled":false},{"price":{"decimal":1.7700,"fractional":"77/100"},"enabled":false},{"price":{"decimal":1.7800,"fractional":"39/50"},"enabled":false},{"price":{"decimal":1.7900,"fractional":"79/100"},"enabled":false},{"price":{"decimal":1.8000,"fractional":"4/5"},"enabled":true},{"price":{"decimal":1.8100,"fractional":"81/100"},"enabled":false},{"price":{"decimal":1.8200,"fractional":"41/50"},"enabled":false},{"price":{"decimal":1.8300,"fractional":"5/6"},"enabled":true},{"price":{"decimal":1.8400,"fractional":"21/25"},"enabled":false},{"price":{"decimal":1.8500,"fractional":"17/20"},"enabled":false},{"price":{"decimal":1.8600,"fractional":"20/23"},"enabled":false},{"price":{"decimal":1.8700,"fractional":"87/100"},"enabled":false},{"price":{"decimal":1.8800,"fractional":"22/25"},"enabled":false},{"price":{"decimal":1.8900,"fractional":"89/100"},"enabled":false},{"price":{"decimal":1.9000,"fractional":"9/10"},"enabled":true},{"price":{"decimal":1.9100,"fractional":"10/11"},"enabled":true},{"price":{"decimal":1.9200,"fractional":"23/25"},"enabled":false},{"price":{"decimal":1.9300,"fractional":"93/100"},"enabled":false},{"price":{"decimal":1.9400,"fractional":"47/50"},"enabled":false},{"price":{"decimal":1.9500,"fractional":"20/21"},"enabled":true},{"price":{"decimal":1.9600,"fractional":"24/25"},"enabled":false},{"price":{"decimal":1.9700,"fractional":"97/100"},"enabled":false},{"price":{"decimal":1.9800,"fractional":"49/50"},"enabled":false},{"price":{"decimal":1.9900,"fractional":"99/100"},"enabled":false},{"price":{"decimal":2.0000,"fractional":"1/1"},"enabled":true},{"price":{"decimal":2.0100,"fractional":"101/100"},"enabled":false},{"price":{"decimal":2.0200,"fractional":"51/50"},"enabled":false},{"price":{"decimal":2.0300,"fractional":"103/100"},"enabled":false},{"price":{"decimal":2.0400,"fractional":"26/25"},"enabled":false},{"price":{"decimal":2.0500,"fractional":"21/20"},"enabled":true},{"price":{"decimal":2.0600,"fractional":"53/50"},"enabled":false},{"price":{"decimal":2.0700,"fractional":"107/100"},"enabled":false},{"price":{"decimal":2.0800,"fractional":"27/25"},"enabled":false},{"price":{"decimal":2.0900,"fractional":"109/100"},"enabled":false},{"price":{"decimal":2.1000,"fractional":"11/10"},"enabled":true},{"price":{"decimal":2.1100,"fractional":"111/100"},"enabled":false},{"price":{"decimal":2.1200,"fractional":"28/25"},"enabled":false},{"price":{"decimal":2.1300,"fractional":"113/100"},"enabled":false},{"price":{"decimal":2.1400,"fractional":"57/50"},"enabled":false},{"price":{"decimal":2.1500,"fractional":"23/20"},"enabled":true},{"price":{"decimal":2.1600,"fractional":"29/25"},"enabled":false},{"price":{"decimal":2.1700,"fractional":"117/100"},"enabled":false},{"price":{"decimal":2.1800,"fractional":"59/50"},"enabled":false},{"price":{"decimal":2.1900,"fractional":"119/100"},"enabled":false},{"price":{"decimal":2.2000,"fractional":"6/5"},"enabled":true},{"price":{"decimal":2.2100,"fractional":"121/100"},"enabled":false},{"price":{"decimal":2.2200,"fractional":"61/50"},"enabled":false},{"price":{"decimal":2.2300,"fractional":"123/100"},"enabled":false},{"price":{"decimal":2.2400,"fractional":"31/25"},"enabled":false},{"price":{"decimal":2.2500,"fractional":"5/4"},"enabled":true},{"price":{"decimal":2.2600,"fractional":"63/50"},"enabled":false},{"price":{"decimal":2.2700,"fractional":"127/100"},"enabled":false},{"price":{"decimal":2.2800,"fractional":"32/25"},"enabled":false},{"price":{"decimal":2.3000,"fractional":"13/10"},"enabled":true},{"price":{"decimal":2.3200,"fractional":"33/25"},"enabled":false},{"price":{"decimal":2.3400,"fractional":"67/50"},"enabled":false},{"price":{"decimal":2.3500,"fractional":"27/20"},"enabled":false},{"price":{"decimal":2.3600,"fractional":"34/25"},"enabled":false},{"price":{"decimal":2.3700,"fractional":"11/8"},"enabled":true},{"price":{"decimal":2.4000,"fractional":"7/5"},"enabled":true},{"price":{"decimal":2.4200,"fractional":"71/50"},"enabled":false},{"price":{"decimal":2.4400,"fractional":"36/25"},"enabled":false},{"price":{"decimal":2.4500,"fractional":"29/20"},"enabled":true},{"price":{"decimal":2.4600,"fractional":"73/50"},"enabled":false},{"price":{"decimal":2.4800,"fractional":"37/25"},"enabled":false},{"price":{"decimal":2.5000,"fractional":"6/4"},"enabled":true},{"price":{"decimal":2.5200,"fractional":"38/25"},"enabled":false},{"price":{"decimal":2.5400,"fractional":"77/50"},"enabled":false},{"price":{"decimal":2.5600,"fractional":"39/25"},"enabled":false},{"price":{"decimal":2.5800,"fractional":"79/50"},"enabled":false},{"price":{"decimal":2.6000,"fractional":"8/5"},"enabled":true},{"price":{"decimal":2.6200,"fractional":"13/8"},"enabled":true},{"price":{"decimal":2.6400,"fractional":"41/25"},"enabled":false},{"price":{"decimal":2.6600,"fractional":"83/50"},"enabled":false},{"price":{"decimal":2.6800,"fractional":"42/25"},"enabled":false},{"price":{"decimal":2.7000,"fractional":"17/10"},"enabled":true},{"price":{"decimal":2.7200,"fractional":"43/25"},"enabled":false},{"price":{"decimal":2.7400,"fractional":"87/50"},"enabled":false},{"price":{"decimal":2.7500,"fractional":"7/4"},"enabled":true},{"price":{"decimal":2.7600,"fractional":"44/25"},"enabled":false},{"price":{"decimal":2.7800,"fractional":"89/50"},"enabled":false},{"price":{"decimal":2.8000,"fractional":"9/5"},"enabled":true},{"price":{"decimal":2.8200,"fractional":"91/50"},"enabled":false},{"price":{"decimal":2.8400,"fractional":"46/25"},"enabled":false},{"price":{"decimal":2.8600,"fractional":"93/50"},"enabled":false},{"price":{"decimal":2.8700,"fractional":"15/8"},"enabled":false},{"price":{"decimal":2.8800,"fractional":"15/8"},"enabled":false},{"price":{"decimal":2.9000,"fractional":"19/10"},"enabled":true},{"price":{"decimal":2.9200,"fractional":"48/25"},"enabled":false},{"price":{"decimal":2.9400,"fractional":"97/50"},"enabled":true},{"price":{"decimal":2.9600,"fractional":"49/25"},"enabled":false},{"price":{"decimal":2.9800,"fractional":"99/50"},"enabled":false},{"price":{"decimal":3.0000,"fractional":"2/1"},"enabled":true},{"price":{"decimal":3.0500,"fractional":"41/20"},"enabled":false},{"price":{"decimal":3.1000,"fractional":"21/10"},"enabled":true},{"price":{"decimal":3.1250,"fractional":"85/40"},"enabled":true},{"price":{"decimal":3.1500,"fractional":"43/20"},"enabled":false},{"price":{"decimal":3.2000,"fractional":"11/5"},"enabled":true},{"price":{"decimal":3.2500,"fractional":"9/4"},"enabled":true},{"price":{"decimal":3.3000,"fractional":"23/10"},"enabled":true},{"price":{"decimal":3.3500,"fractional":"47/20"},"enabled":false},{"price":{"decimal":3.4000,"fractional":"12/5"},"enabled":true},{"price":{"decimal":3.4500,"fractional":"49/20"},"enabled":false},{"price":{"decimal":3.5000,"fractional":"5/2"},"enabled":true},{"price":{"decimal":3.5500,"fractional":"51/20"},"enabled":false},{"price":{"decimal":3.6000,"fractional":"13/5"},"enabled":true},{"price":{"decimal":3.6500,"fractional":"53/20"},"enabled":false},{"price":{"decimal":3.7000,"fractional":"27/10"},"enabled":false},{"price":{"decimal":3.7500,"fractional":"11/4"},"enabled":true},{"price":{"decimal":3.8000,"fractional":"14/5"},"enabled":true},{"price":{"decimal":3.8500,"fractional":"57/20"},"enabled":false},{"price":{"decimal":3.9500,"fractional":"59/20"},"enabled":false},{"price":{"decimal":4.0000,"fractional":"3/1"},"enabled":true},{"price":{"decimal":4.0500,"fractional":"61/20"},"enabled":false},{"price":{"decimal":4.1000,"fractional":"31/10"},"enabled":true},{"price":{"decimal":4.1500,"fractional":"63/20"},"enabled":false},{"price":{"decimal":4.2000,"fractional":"16/5"},"enabled":true},{"price":{"decimal":4.2500,"fractional":"13/4"},"enabled":false},{"price":{"decimal":4.3000,"fractional":"33/10"},"enabled":false},{"price":{"decimal":4.3300,"fractional":"10/3"},"enabled":true},{"price":{"decimal":4.3500,"fractional":"67/20"},"enabled":false},{"price":{"decimal":4.4000,"fractional":"17/5"},"enabled":true},{"price":{"decimal":4.4500,"fractional":"69/20"},"enabled":false},{"price":{"decimal":4.5000,"fractional":"7/2"},"enabled":true},{"price":{"decimal":4.5500,"fractional":"71/20"},"enabled":false},{"price":{"decimal":4.6000,"fractional":"18/5"},"enabled":true},{"price":{"decimal":4.6500,"fractional":"73/20"},"enabled":false},{"price":{"decimal":4.7000,"fractional":"37/10"},"enabled":false},{"price":{"decimal":4.7500,"fractional":"15/4"},"enabled":true},{"price":{"decimal":4.8000,"fractional":"19/5"},"enabled":true},{"price":{"decimal":4.8500,"fractional":"77/20"},"enabled":false},{"price":{"decimal":4.9000,"fractional":"39/10"},"enabled":false},{"price":{"decimal":4.9500,"fractional":"79/20"},"enabled":false},{"price":{"decimal":5.0000,"fractional":"4/1"},"enabled":true},{"price":{"decimal":5.1000,"fractional":"41/10"},"enabled":false},{"price":{"decimal":5.2000,"fractional":"21/5"},"enabled":false},{"price":{"decimal":5.3000,"fractional":"43/10"},"enabled":false},{"price":{"decimal":5.4000,"fractional":"22/5"},"enabled":false},{"price":{"decimal":5.5000,"fractional":"9/2"},"enabled":true},{"price":{"decimal":5.6000,"fractional":"23/5"},"enabled":false},{"price":{"decimal":5.7000,"fractional":"47/10"},"enabled":false},{"price":{"decimal":5.8000,"fractional":"24/5"},"enabled":false},{"price":{"decimal":5.9000,"fractional":"49/10"},"enabled":false},{"price":{"decimal":6.0000,"fractional":"5/1"},"enabled":true},{"price":{"decimal":6.2000,"fractional":"26/5"},"enabled":false},{"price":{"decimal":6.4000,"fractional":"27/5"},"enabled":false},{"price":{"decimal":6.5000,"fractional":"11/2"},"enabled":true},{"price":{"decimal":6.6000,"fractional":"28/5"},"enabled":false},{"price":{"decimal":6.8000,"fractional":"29/5"},"enabled":false},{"price":{"decimal":7.0000,"fractional":"6/1"},"enabled":true},{"price":{"decimal":7.2000,"fractional":"31/5"},"enabled":false},{"price":{"decimal":7.4000,"fractional":"32/5"},"enabled":false},{"price":{"decimal":7.5000,"fractional":"13/2"},"enabled":true},{"price":{"decimal":7.6000,"fractional":"33/5"},"enabled":false},{"price":{"decimal":7.8000,"fractional":"34/5"},"enabled":false},{"price":{"decimal":8.0000,"fractional":"7/1"},"enabled":true},{"price":{"decimal":8.2000,"fractional":"36/5"},"enabled":false},{"price":{"decimal":8.4000,"fractional":"37/5"},"enabled":false},{"price":{"decimal":8.5000,"fractional":"15/2"},"enabled":true},{"price":{"decimal":8.6000,"fractional":"38/5"},"enabled":false},{"price":{"decimal":8.8000,"fractional":"39/5"},"enabled":false},{"price":{"decimal":9.0000,"fractional":"8/1"},"enabled":true},{"price":{"decimal":9.2000,"fractional":"41/5"},"enabled":false},{"price":{"decimal":9.4000,"fractional":"42/5"},"enabled":false},{"price":{"decimal":9.5000,"fractional":"17/2"},"enabled":true},{"price":{"decimal":9.6000,"fractional":"43/5"},"enabled":false},{"price":{"decimal":9.8000,"fractional":"44/5"},"enabled":false},{"price":{"decimal":10.0000,"fractional":"9/1"},"enabled":true},{"price":{"decimal":11.0000,"fractional":"10/1"},"enabled":true},{"price":{"decimal":12.0000,"fractional":"11/1"},"enabled":true},{"price":{"decimal":13.0000,"fractional":"12/1"},"enabled":true},{"price":{"decimal":14.0000,"fractional":"13/1"},"enabled":true},{"price":{"decimal":15.0000,"fractional":"14/1"},"enabled":true},{"price":{"decimal":16.0000,"fractional":"15/1"},"enabled":true},{"price":{"decimal":17.0000,"fractional":"16/1"},"enabled":true},{"price":{"decimal":19.0000,"fractional":"18/1"},"enabled":true},{"price":{"decimal":21.0000,"fractional":"20/1"},"enabled":true},{"price":{"decimal":23.0000,"fractional":"22/1"},"enabled":true},{"price":{"decimal":26.0000,"fractional":"25/1"},"enabled":true},{"price":{"decimal":29.0000,"fractional":"28/1"},"enabled":true},{"price":{"decimal":31.0000,"fractional":"30/1"},"enabled":true},{"price":{"decimal":34.0000,"fractional":"33/1"},"enabled":true},{"price":{"decimal":36.0000,"fractional":"35/1"},"enabled":true},{"price":{"decimal":41.0000,"fractional":"40/1"},"enabled":true},{"price":{"decimal":46.0000,"fractional":"45/1"},"enabled":true},{"price":{"decimal":51.0000,"fractional":"50/1"},"enabled":true},{"price":{"decimal":56.0000,"fractional":"55/1"},"enabled":true},{"price":{"decimal":61.0000,"fractional":"60/1"},"enabled":true},{"price":{"decimal":67.0000,"fractional":"66/1"},"enabled":true},{"price":{"decimal":71.0000,"fractional":"70/1"},"enabled":true},{"price":{"decimal":76.0000,"fractional":"75/1"},"enabled":false},{"price":{"decimal":81.0000,"fractional":"80/1"},"enabled":true},{"price":{"decimal":86.0000,"fractional":"85/1"},"enabled":false},{"price":{"decimal":91.0000,"fractional":"90/1"},"enabled":true},{"price":{"decimal":96.0000,"fractional":"95/1"},"enabled":false},{"price":{"decimal":101.0000,"fractional":"100/1"},"enabled":true},{"price":{"decimal":111.0000,"fractional":"110/1"},"enabled":true},{"price":{"decimal":121.0000,"fractional":"120/1"},"enabled":true},{"price":{"decimal":126.0000,"fractional":"125/1"},"enabled":true},{"price":{"decimal":131.0000,"fractional":"130/1"},"enabled":true},{"price":{"decimal":141.0000,"fractional":"140/1"},"enabled":true},{"price":{"decimal":151.0000,"fractional":"150/1"},"enabled":true},{"price":{"decimal":176.0000,"fractional":"175/1"},"enabled":true},{"price":{"decimal":201.0000,"fractional":"200/1"},"enabled":true},{"price":{"decimal":226.0000,"fractional":"225/1"},"enabled":true},{"price":{"decimal":251.0000,"fractional":"250/1"},"enabled":true},{"price":{"decimal":276.0000,"fractional":"275/1"},"enabled":true},{"price":{"decimal":301.0000,"fractional":"300/1"},"enabled":true},{"price":{"decimal":401.0000,"fractional":"400/1"},"enabled":true},{"price":{"decimal":501.0000,"fractional":"500/1"},"enabled":true},{"price":{"decimal":1001.0000,"fractional":"1000/1"},"enabled":true}],"matchStrategy":"floor"}, \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 5273127..fe29c0b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,12 +10,22 @@ pub enum FractionStrategy { Simplify, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LookupVariant { + /// No lookup + None, + /// Basic lookup for common values usually matching closely the original value + Basic, + /// Extended lookup - covers more values but also gives more rounded results, f. ex. 1.0013 -> 1/750 instead of 1/768 + Extended, +} + /// Configuration for conversion functions. #[derive(Debug, Clone, Copy)] pub struct ConversionConfig { /// Use lookup tables first for conversion, then fallback to regular computations /// Note: When using lookup tables feature, conversion from 1.67 or -150 gives 4/6 instead of 2/3 (see README.md) - pub use_lookup_tables: bool, + pub lookup_tables_variant: LookupVariant, /// Fractions computing strategy pub fraction_strategy: FractionStrategy, /// Rounding method for Decimal type @@ -34,28 +44,33 @@ impl Default for ConversionConfig { } static DEFAULT_CONVERSION_CONFIG: ConversionConfig = ConversionConfig { - use_lookup_tables: true, + lookup_tables_variant: LookupVariant::Basic, fraction_strategy: FractionStrategy::Simplify, rounding_strategy: RoundingStrategy::MidpointAwayFromZero, // former RoundHalfUp }; impl ConversionConfig { - pub fn no_lookup(&mut self) -> &mut Self { - self.use_lookup_tables = false; + pub fn no_lookup(mut self) -> Self { + self.lookup_tables_variant = LookupVariant::None; + self + } + + pub fn extended_lookup(mut self) -> Self { + self.lookup_tables_variant = LookupVariant::Extended; self } - pub fn plain_fraction_strategy(&mut self) -> &mut Self { + pub fn plain_fraction_strategy(mut self) -> Self { self.fraction_strategy = FractionStrategy::Plain; self } - pub fn fraction_strategy(&mut self, strategy: FractionStrategy) -> &mut Self { + pub fn fraction_strategy(mut self, strategy: FractionStrategy) -> Self { self.fraction_strategy = strategy; self } - pub fn rounding_strategy(&mut self, strategy: RoundingStrategy) -> &mut Self { + pub fn rounding_strategy(mut self, strategy: RoundingStrategy) -> Self { self.rounding_strategy = strategy; self } diff --git a/src/convert.rs b/src/convert.rs index 07cc33d..bc8b315 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -2,9 +2,11 @@ use rust_decimal::{Decimal, prelude::ToPrimitive}; use rust_decimal_macros::dec; use crate::{ - ConversionConfig, FractionStrategy, + ConversionConfig, FractionStrategy, LookupVariant, lookup_tables::{ - get_american_to_decimal_map, get_american_to_fraction_map, get_decimal_to_fraction_map, + get_american_to_decimal_extended_map, get_american_to_decimal_map, + get_american_to_fraction_extended_map, get_american_to_fraction_map, + get_decimal_to_fraction_extended_map, get_decimal_to_fraction_map, }, }; @@ -22,10 +24,21 @@ pub fn american_to_decimal_custom( return Err(ConversionError::AmericanZero); } - if config.use_lookup_tables - && let Some(ret) = get_american_to_decimal_map().get(&value) - { - return Ok(*ret); + match config.lookup_tables_variant { + LookupVariant::Basic => { + if let Some(ret) = get_american_to_decimal_map().get(&value) { + return Ok(*ret); + } + } + LookupVariant::Extended => { + if let Some(ret) = get_american_to_decimal_map() + .get(&value) + .or(get_american_to_decimal_extended_map().get(&value)) + { + return Ok(*ret); + } + } + _ => (), } american_to_decimal_inner(value) @@ -61,10 +74,21 @@ pub fn decimal_to_fractional_custom( value: Decimal, config: &ConversionConfig, ) -> Result<(u32, u32), ConversionError> { - if config.use_lookup_tables - && let Some(ret) = get_decimal_to_fraction_map().get(&value) - { - return Ok(*ret); + match config.lookup_tables_variant { + LookupVariant::Basic => { + if let Some(ret) = get_decimal_to_fraction_map().get(&value) { + return Ok(*ret); + } + } + LookupVariant::Extended => { + if let Some(ret) = get_decimal_to_fraction_map() + .get(&value) + .or(get_decimal_to_fraction_extended_map().get(&value)) + { + return Ok(*ret); + } + } + _ => (), } match config.fraction_strategy { @@ -119,7 +143,7 @@ pub fn decimal_to_fractional_simplify(value: Decimal) -> Result<(u32, u32), Conv // value is, the bigger the epsilon can be to be more roundish-like, // 1.333 -> 1/3 (bigger epsilon) // 1.001 -> 1/1000 (smaller epsilon) - let epsilon = (value - Decimal::ONE).min(dec!(0.05)); + let epsilon = (value - Decimal::ONE).min(dec!(0.01)); // Standard algorithm to find best rational approximation. let mut a = fractional_part; @@ -176,10 +200,21 @@ pub fn american_to_fractional_custom( value: i32, config: &ConversionConfig, ) -> Result<(u32, u32), ConversionError> { - if config.use_lookup_tables - && let Some(ret) = get_american_to_fraction_map().get(&value) - { - return Ok(*ret); + match config.lookup_tables_variant { + LookupVariant::Basic => { + if let Some(ret) = get_american_to_fraction_map().get(&value) { + return Ok(*ret); + } + } + LookupVariant::Extended => { + if let Some(ret) = get_american_to_fraction_map() + .get(&value) + .or(get_american_to_fraction_extended_map().get(&value)) + { + return Ok(*ret); + } + } + _ => (), } let decimal = american_to_decimal_inner(value)?; @@ -273,7 +308,7 @@ mod tests { assert_decimal_eq(american_to_decimal(-150).unwrap(), dec!(1.67)); assert_decimal_eq( - american_to_decimal_custom(-150, ConversionConfig::default().no_lookup()).unwrap(), + american_to_decimal_custom(-150, &ConversionConfig::default().no_lookup()).unwrap(), dec!(1.666), ); @@ -379,7 +414,7 @@ mod tests { // The same without lookup table assert_eq!( - american_to_fractional_custom(-150, ConversionConfig::default().no_lookup()), + american_to_fractional_custom(-150, &ConversionConfig::default().no_lookup()), Ok((2, 3)) ); @@ -419,7 +454,7 @@ mod tests { assert_eq!( super::decimal_to_fractional_custom( dec!(1.33), - ConversionConfig::default().plain_fraction_strategy() + &ConversionConfig::default().plain_fraction_strategy() ), Ok((1, 3)) ); @@ -428,7 +463,7 @@ mod tests { assert_eq!( super::decimal_to_fractional_custom( dec!(1.33), - ConversionConfig::default() + &ConversionConfig::default() .plain_fraction_strategy() .no_lookup() ), @@ -439,7 +474,7 @@ mod tests { assert_eq!( super::decimal_to_fractional_custom( dec!(1.333), - ConversionConfig::default().plain_fraction_strategy() + &ConversionConfig::default().plain_fraction_strategy() ), Ok((333, 1000)) ); @@ -480,4 +515,303 @@ mod tests { assert_eq!(normalize_american_odds(-1), 10000); assert_eq!(normalize_american_odds(-99), 101); } + + #[test] + #[rustfmt::skip] + fn extended_lookup_test() { + let config = &ConversionConfig::default().extended_lookup(); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0010), config), Ok((1, 1000))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0013), config), Ok((1, 750))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0020), config), Ok((1, 500))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0025), config), Ok((1, 400))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0030), config), Ok((1, 300))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0040), config), Ok((1, 250))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0050), config), Ok((1, 200))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0070), config), Ok((1, 150))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0100), config), Ok((1, 100))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0120), config), Ok((1, 80))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0150), config), Ok((1, 66))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0200), config), Ok((1, 50))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0250), config), Ok((1, 40))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0300), config), Ok((1, 33))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0400), config), Ok((1, 25))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0500), config), Ok((1, 20))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0550), config), Ok((1, 18))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0600), config), Ok((1, 16))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0700), config), Ok((1, 14))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0800), config), Ok((1, 12))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.0900), config), Ok((1, 11))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1000), config), Ok((1, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1100), config), Ok((1, 9))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1200), config), Ok((1, 8))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1300), config), Ok((2, 15))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1400), config), Ok((1, 7))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1500), config), Ok((2, 13))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1600), config), Ok((1, 6))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1800), config), Ok((2, 11))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.1900), config), Ok((19, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2000), config), Ok((1, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2100), config), Ok((21, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2200), config), Ok((2, 9))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2300), config), Ok((23, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2400), config), Ok((6, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2500), config), Ok((1, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2600), config), Ok((13, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2700), config), Ok((27, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.2900), config), Ok((2, 7))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3000), config), Ok((3, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3100), config), Ok((31, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3200), config), Ok((8, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3300), config), Ok((1, 3))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3400), config), Ok((17, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3500), config), Ok((7, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3600), config), Ok((4, 11))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3700), config), Ok((37, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3800), config), Ok((19, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.3900), config), Ok((39, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4000), config), Ok((2, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4100), config), Ok((41, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4200), config), Ok((21, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4300), config), Ok((43, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4400), config), Ok((4, 9))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4500), config), Ok((9, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4600), config), Ok((23, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4700), config), Ok((40, 85))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4800), config), Ok((12, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.4900), config), Ok((49, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5000), config), Ok((1, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5100), config), Ok((51, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5200), config), Ok((13, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5300), config), Ok((8, 15))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5400), config), Ok((27, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5500), config), Ok((11, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5600), config), Ok((14, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5700), config), Ok((4, 7))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5800), config), Ok((29, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.5900), config), Ok((59, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6000), config), Ok((3, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6100), config), Ok((8, 13))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6300), config), Ok((63, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6400), config), Ok((16, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6500), config), Ok((13, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6600), config), Ok((4, 6))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6800), config), Ok((34, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.6900), config), Ok((69, 100))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7000), config), Ok((7, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7100), config), Ok((71, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7200), config), Ok((8, 11))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7400), config), Ok((37, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7500), config), Ok((3, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7600), config), Ok((19, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7700), config), Ok((77, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7800), config), Ok((39, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.7900), config), Ok((79, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8000), config), Ok((4, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8100), config), Ok((81, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8200), config), Ok((41, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8300), config), Ok((5, 6))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8400), config), Ok((21, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8500), config), Ok((17, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8600), config), Ok((20, 23))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8700), config), Ok((87, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8800), config), Ok((22, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.8900), config), Ok((89, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9000), config), Ok((9, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9100), config), Ok((10, 11))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9200), config), Ok((23, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9300), config), Ok((93, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9400), config), Ok((47, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9500), config), Ok((20, 21))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9600), config), Ok((24, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9700), config), Ok((97, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9800), config), Ok((49, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(1.9900), config), Ok((99, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0000), config), Ok((1, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0100), config), Ok((101, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0200), config), Ok((51, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0300), config), Ok((103, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0400), config), Ok((26, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0500), config), Ok((21, 20))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0600), config), Ok((53, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0700), config), Ok((107, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0800), config), Ok((27, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.0900), config), Ok((109, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1000), config), Ok((11, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1100), config), Ok((111, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1200), config), Ok((28, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1300), config), Ok((113, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1400), config), Ok((57, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1500), config), Ok((23, 20))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1600), config), Ok((29, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1700), config), Ok((117, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1800), config), Ok((59, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.1900), config), Ok((119, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2000), config), Ok((6, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2100), config), Ok((121, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2200), config), Ok((61, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2300), config), Ok((123, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2400), config), Ok((31, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2500), config), Ok((5, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2600), config), Ok((63, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2700), config), Ok((127, 100))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.2800), config), Ok((32, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3000), config), Ok((13, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3200), config), Ok((33, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3400), config), Ok((67, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3500), config), Ok((27, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3600), config), Ok((34, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.3700), config), Ok((11, 8))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4000), config), Ok((7, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4200), config), Ok((71, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4400), config), Ok((36, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4500), config), Ok((29, 20))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4600), config), Ok((73, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.4800), config), Ok((37, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.5000), config), Ok((6, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.5200), config), Ok((38, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.5400), config), Ok((77, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.5600), config), Ok((39, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.5800), config), Ok((79, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.6000), config), Ok((8, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.6200), config), Ok((13, 8))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.6400), config), Ok((41, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.6600), config), Ok((83, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.6800), config), Ok((42, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7000), config), Ok((17, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7200), config), Ok((43, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7400), config), Ok((87, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7500), config), Ok((7, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7600), config), Ok((44, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.7800), config), Ok((89, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8000), config), Ok((9, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8200), config), Ok((91, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8400), config), Ok((46, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8600), config), Ok((93, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8700), config), Ok((15, 8))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.8800), config), Ok((15, 8))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.9000), config), Ok((19, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.9200), config), Ok((48, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.9400), config), Ok((97, 50))); + assert_eq!(super::decimal_to_fractional_custom(dec!(2.9600), config), Ok((49, 25))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(2.9800), config), Ok((99, 50))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.0000), config), Ok((2, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.0500), config), Ok((41, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.1000), config), Ok((21, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.1250), config), Ok((85, 40))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.1500), config), Ok((43, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.2000), config), Ok((11, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.2500), config), Ok((9, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.3000), config), Ok((23, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.3500), config), Ok((47, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.4000), config), Ok((12, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.4500), config), Ok((49, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.5000), config), Ok((5, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.5500), config), Ok((51, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.6000), config), Ok((13, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.6500), config), Ok((53, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.7000), config), Ok((27, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.7500), config), Ok((11, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.8000), config), Ok((14, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(3.8500), config), Ok((57, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(3.9500), config), Ok((59, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.0000), config), Ok((3, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.0500), config), Ok((61, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.1000), config), Ok((31, 10))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.1500), config), Ok((63, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.2000), config), Ok((16, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.2500), config), Ok((13, 4))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.3000), config), Ok((33, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.3300), config), Ok((10, 3))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.3500), config), Ok((67, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.4000), config), Ok((17, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.4500), config), Ok((69, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.5000), config), Ok((7, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.5500), config), Ok((71, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.6000), config), Ok((18, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.6500), config), Ok((73, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.7000), config), Ok((37, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.7500), config), Ok((15, 4))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.8000), config), Ok((19, 5))); + assert_eq!(super::decimal_to_fractional_custom(dec!(4.8500), config), Ok((77, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.9000), config), Ok((39, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(4.9500), config), Ok((79, 20))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.0000), config), Ok((4, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(5.1000), config), Ok((41, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.2000), config), Ok((21, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.3000), config), Ok((43, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.4000), config), Ok((22, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.5000), config), Ok((9, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(5.6000), config), Ok((23, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.7000), config), Ok((47, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.8000), config), Ok((24, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(5.9000), config), Ok((49, 10))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(6.0000), config), Ok((5, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(6.2000), config), Ok((26, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(6.4000), config), Ok((27, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(6.5000), config), Ok((11, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(6.6000), config), Ok((28, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(6.8000), config), Ok((29, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(7.0000), config), Ok((6, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(7.2000), config), Ok((31, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(7.4000), config), Ok((32, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(7.5000), config), Ok((13, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(7.6000), config), Ok((33, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(7.8000), config), Ok((34, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(8.0000), config), Ok((7, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(8.2000), config), Ok((36, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(8.4000), config), Ok((37, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(8.5000), config), Ok((15, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(8.6000), config), Ok((38, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(8.8000), config), Ok((39, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(9.0000), config), Ok((8, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(9.2000), config), Ok((41, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(9.4000), config), Ok((42, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(9.5000), config), Ok((17, 2))); + assert_eq!(super::decimal_to_fractional_custom(dec!(9.6000), config), Ok((43, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(9.8000), config), Ok((44, 5))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(10.0000), config), Ok((9, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(11.0000), config), Ok((10, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(12.0000), config), Ok((11, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(13.0000), config), Ok((12, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(14.0000), config), Ok((13, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(15.0000), config), Ok((14, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(16.0000), config), Ok((15, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(17.0000), config), Ok((16, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(19.0000), config), Ok((18, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(21.0000), config), Ok((20, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(23.0000), config), Ok((22, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(26.0000), config), Ok((25, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(29.0000), config), Ok((28, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(31.0000), config), Ok((30, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(34.0000), config), Ok((33, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(36.0000), config), Ok((35, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(41.0000), config), Ok((40, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(46.0000), config), Ok((45, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(51.0000), config), Ok((50, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(56.0000), config), Ok((55, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(61.0000), config), Ok((60, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(67.0000), config), Ok((66, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(71.0000), config), Ok((70, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(76.0000), config), Ok((75, 1))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(81.0000), config), Ok((80, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(86.0000), config), Ok((85, 1))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(91.0000), config), Ok((90, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(96.0000), config), Ok((95, 1))); //disabled + assert_eq!(super::decimal_to_fractional_custom(dec!(101.0000), config), Ok((100, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(111.0000), config), Ok((110, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(121.0000), config), Ok((120, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(126.0000), config), Ok((125, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(131.0000), config), Ok((130, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(141.0000), config), Ok((140, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(151.0000), config), Ok((150, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(176.0000), config), Ok((175, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(201.0000), config), Ok((200, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(226.0000), config), Ok((225, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(251.0000), config), Ok((250, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(276.0000), config), Ok((275, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(301.0000), config), Ok((300, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(401.0000), config), Ok((400, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(501.0000), config), Ok((500, 1))); + assert_eq!(super::decimal_to_fractional_custom(dec!(1001.0000), config), Ok((1000, 1))); + } } diff --git a/src/lookup_tables.rs b/src/lookup_tables.rs index f5a5778..b52a4e3 100644 --- a/src/lookup_tables.rs +++ b/src/lookup_tables.rs @@ -80,6 +80,48 @@ pub fn get_decimal_to_fraction_map() -> &'static HashMap { m.insert(dec!(67), (66, 1)); m.insert(dec!(101), (100, 1)); m.insert(dec!(1001), (1000, 1)); + + m + }) +} + +// Accessor for DECIMAL_TO_FRACTION extended Map +static DECIMAL_TO_FRACTION_EXTENDED: OnceLock> = OnceLock::new(); + +/// Extended lookup table for conversion from decimal to fractional. +pub fn get_decimal_to_fraction_extended_map() -> &'static HashMap { + DECIMAL_TO_FRACTION_EXTENDED.get_or_init(|| { + let mut m = HashMap::new(); + m.insert(dec!(1.0013), (1, 750)); + m.insert(dec!(1.0030), (1, 300)); + m.insert(dec!(1.0070), (1, 150)); + m.insert(dec!(1.0120), (1, 80)); + m.insert(dec!(1.0150), (1, 66)); + m.insert(dec!(1.0300), (1, 33)); + m.insert(dec!(1.0550), (1, 18)); + m.insert(dec!(1.0600), (1, 16)); + m.insert(dec!(1.0700), (1, 14)); + m.insert(dec!(1.0800), (1, 12)); + m.insert(dec!(1.0900), (1, 11)); + m.insert(dec!(1.1100), (1, 9)); + m.insert(dec!(1.1200), (1, 8)); + m.insert(dec!(1.1300), (2, 15)); + m.insert(dec!(1.1400), (1, 7)); + m.insert(dec!(1.1500), (2, 13)); + m.insert(dec!(1.1600), (1, 6)); + m.insert(dec!(1.1800), (2, 11)); // D + m.insert(dec!(1.4700), (40, 85)); + m.insert(dec!(1.6100), (8, 13)); + m.insert(dec!(1.6600), (4, 6)); + m.insert(dec!(1.6800), (34, 50)); // D + m.insert(dec!(1.7200), (8, 11)); + m.insert(dec!(1.8600), (20, 23)); // D + m.insert(dec!(1.9500), (20, 21)); + m.insert(dec!(1.9600), (24, 25)); // D + m.insert(dec!(1.9800), (49, 50)); // D + m.insert(dec!(2.3700), (11, 8)); + m.insert(dec!(2.8700), (15, 8)); // D + m.insert(dec!(3.1250), (85, 40)); m }) } @@ -164,6 +206,14 @@ pub fn get_american_to_fraction_map() -> &'static HashMap { }) } +// Accessor for AMERICAN_TO_FRACTION extended Map +static AMERICAN_TO_FRACTION_EXTENDED: OnceLock> = OnceLock::new(); + +/// Extended lookup table for conversion from american to fractional. +pub fn get_american_to_fraction_extended_map() -> &'static HashMap { + AMERICAN_TO_FRACTION_EXTENDED.get_or_init(HashMap::new) +} + // Accessor for AMERICAN_TO_DECIMAL Map static AMERICAN_TO_DECIMAL: OnceLock> = OnceLock::new(); @@ -243,3 +293,12 @@ pub fn get_american_to_decimal_map() -> &'static HashMap { m }) } + +// Accessor for AMERICAN_TO_DECIMAL extended Map +static AMERICAN_TO_DECIMAL_EXTENDED: OnceLock> = OnceLock::new(); + +/// Extended lookup table for conversion from american to decimal. +pub fn get_american_to_decimal_extended_map() -> &'static HashMap { + // TODO + AMERICAN_TO_DECIMAL_EXTENDED.get_or_init(HashMap::new) +} diff --git a/src/odds.rs b/src/odds.rs index f13153a..9100697 100644 --- a/src/odds.rs +++ b/src/odds.rs @@ -185,10 +185,7 @@ mod tests { assert_eq!(american.to_fractional(), Ok((4, 6))); assert_eq!( - american.to_fractional_custom(&ConversionConfig { - use_lookup_tables: false, - ..Default::default() - }), + american.to_fractional_custom(&ConversionConfig::default().no_lookup()), Ok((2, 3)) ); @@ -228,10 +225,7 @@ mod tests { assert_eq!( Odds::American(-150) - .to_fractional_str_custom(&ConversionConfig { - use_lookup_tables: false, - ..Default::default() - }) + .to_fractional_str_custom(&ConversionConfig::default().no_lookup()) .unwrap(), "2/3" );