From c2dad08fef7d5eb2db93359a121f3b0123e5e777 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Sat, 5 May 2018 00:40:54 +0900 Subject: [PATCH] Can solve inverse of currency pair --- BTCPayServer.Tests/RateRulesTest.cs | 9 +++++++++ BTCPayServer/BTCPayServer.csproj | 2 +- BTCPayServer/Rating/CurrencyPair.cs | 5 +++++ BTCPayServer/Rating/RateRules.cs | 25 ++++++++++++++----------- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/BTCPayServer.Tests/RateRulesTest.cs b/BTCPayServer.Tests/RateRulesTest.cs index d82b287d1..f12736855 100644 --- a/BTCPayServer.Tests/RateRulesTest.cs +++ b/BTCPayServer.Tests/RateRulesTest.cs @@ -113,12 +113,21 @@ namespace BTCPayServer.Tests builder.AppendLine("DOGE_BTC = 2000"); Assert.True(RateRules.TryParse(builder.ToString(), out rules)); rules.GlobalMultiplier = 1.1m; + rule2 = rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD")); Assert.Equal("(2000 * (-3 + coinbase(BTC_CAD) + 50 - 5)) * 1.1", rule2.ToString()); rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), 1000m); Assert.True(rule2.Reevaluate()); Assert.Equal("(2000 * (-3 + 1000 + 50 - 5)) * 1.1", rule2.ToString(true)); Assert.Equal((2000m * (-3m + 1000m + 50m - 5m)) * 1.1m, rule2.Value.Value); + + // Test inverse + rule2 = rules.GetRuleFor(CurrencyPair.Parse("USD_DOGE")); + Assert.Equal("(1 / (2000 * (-3 + coinbase(BTC_CAD) + 50 - 5))) * 1.1", rule2.ToString()); + rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), 1000m); + Assert.True(rule2.Reevaluate()); + Assert.Equal("(1 / (2000 * (-3 + 1000 + 50 - 5))) * 1.1", rule2.ToString(true)); + Assert.Equal(( 1.0m / (2000m * (-3m + 1000m + 50m - 5m))) * 1.1m, rule2.Value.Value); //////// } } diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index cd4e8d50f..2b36f82d5 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.0 - 1.0.2.2 + 1.0.2.3 NU1701,CA1816,CA1308,CA1810,CA2208 diff --git a/BTCPayServer/Rating/CurrencyPair.cs b/BTCPayServer/Rating/CurrencyPair.cs index 7ba9cfe5a..c9a6c6e9e 100644 --- a/BTCPayServer/Rating/CurrencyPair.cs +++ b/BTCPayServer/Rating/CurrencyPair.cs @@ -90,5 +90,10 @@ namespace BTCPayServer.Rating { return $"{Left}_{Right}"; } + + public CurrencyPair Inverse() + { + return new CurrencyPair(Right, Left); + } } } diff --git a/BTCPayServer/Rating/RateRules.cs b/BTCPayServer/Rating/RateRules.cs index 61772a14f..b7c7f20bc 100644 --- a/BTCPayServer/Rating/RateRules.cs +++ b/BTCPayServer/Rating/RateRules.cs @@ -133,28 +133,30 @@ namespace BTCPayServer.Rating if (currencyPair.Left == "X" || currencyPair.Right == "X") throw new ArgumentException(paramName: nameof(currencyPair), message: "Invalid X currency"); var candidate = FindBestCandidate(currencyPair); - if (GlobalMultiplier != decimal.One) { candidate = CreateExpression($"({candidate}) * {GlobalMultiplier.ToString(CultureInfo.InvariantCulture)}"); } return new RateRule(this, currencyPair, candidate); } - + public ExpressionSyntax FindBestCandidate(CurrencyPair p) { - var candidates = new List<(CurrencyPair Pair, int Prioriy, ExpressionSyntax Expression)>(); + var invP = p.Inverse(); + var candidates = new List<(CurrencyPair Pair, int Prioriy, ExpressionSyntax Expression, bool Inverse)>(); foreach (var pair in new[] { - (Pair: p, Priority: 0), - (Pair: new CurrencyPair(p.Left, "X"), Priority: 1), - (Pair: new CurrencyPair("X", p.Right), Priority: 1), - (Pair: new CurrencyPair("X", "X"), Priority: 2) + (Pair: p, Priority: 0, Inverse: false), + (Pair: new CurrencyPair(p.Left, "X"), Priority: 1, Inverse: false), + (Pair: new CurrencyPair("X", p.Right), Priority: 1, Inverse: false), + (Pair: new CurrencyPair(invP.Left, "X"), Priority: 2, Inverse: true), + (Pair: new CurrencyPair("X", invP.Right), Priority: 2, Inverse: true), + (Pair: new CurrencyPair("X", "X"), Priority: 3, Inverse: false) }) { if (ruleList.ExpressionsByPair.TryGetValue(pair.Pair, out var expression)) { - candidates.Add((pair.Pair, pair.Priority, expression.Expression)); + candidates.Add((pair.Pair, pair.Priority, expression.Expression, pair.Inverse)); } } if (candidates.Count == 0) @@ -163,8 +165,9 @@ namespace BTCPayServer.Rating .OrderBy(c => c.Prioriy) .ThenBy(c => c.Expression.Span.Start) .First(); - - return best.Expression; + return best.Inverse + ? CreateExpression($"1 / {invP}") + : best.Expression; } internal static ExpressionSyntax CreateExpression(string str) @@ -364,7 +367,7 @@ namespace BTCPayServer.Rating string _ExchangeName = null; public List Errors = new List(); - const int MaxNestedCount = 6; + const int MaxNestedCount = 8; public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) { if (CurrencyPair.TryParse(node.Identifier.ValueText, out var currentPair))