public ConditionOutcome Test(ComparisonContext ctx) { int totalMatch = 0; do { int iterationMatch = 0; if (ctx.CurrentIndex >= ctx.InstructionList.Count) { break; } if (Type == NodeType.Leaf) { if (ctx.InstructionList[ctx.CurrentIndex].OpCode == this.Value) { iterationMatch++; } } else // if (Type == NodeType.Node) { foreach (var v in Childs) { ConditionOutcome outcome = ConditionOutcome.NotMatched; if (Condition != null) { outcome = Condition(ctx, v); } else { outcome = v.Test(ctx); } if (outcome == ConditionOutcome.Matched) { iterationMatch++; if (Mode == TestMode.InRange) { break; } } else if (Mode == TestMode.MatchEverything) { return(ConditionOutcome.NotMatched); } } } if (iterationMatch == 0) { break; } totalMatch += iterationMatch; } while ((Type == NodeType.Leaf || Mode == TestMode.InRange) && (!MaxNumber.HasValue || totalMatch < MaxNumber)); // Reason for returning NotMatched: // 1. If this is a Leaf: // 1.1: Matched number less than MinNumber // 2. If this is a Node: // 2.1: Comparison mode is InRange and matching number is outside this range // 2.2: Comparison mode is MatchEverything and not everything is matched if (((Type == NodeType.Leaf || Mode == TestMode.InRange) && totalMatch < MinNumber) || (Mode == TestMode.MatchEverything && totalMatch != Childs.Count)) { return(ConditionOutcome.NotMatched); } return(ConditionOutcome.Matched); }
public void CreateSampleCondition() { //arrange //create condition for the following case: //when the request is "debit" and the account balance <=0, halt the process var whenRequestIsDebit = new Condition { Active = true, ConditionApplicatorType = ConditionApplicatorType.All, ConditionConnector = ConditionConnector.And, Key = ComparatorKey.Custom, KeyExpression = "$.Payload.TransactionType", Type = ComparatorType.EqualTo, Name = "halt_no_balance", Value = "debit", OutcomeId = 1 //same outcome }; var whenAccountHasNoMoney = new Condition { Active = true, ConditionApplicatorType = ConditionApplicatorType.All, ConditionConnector = ConditionConnector.None, Key = ComparatorKey.Balance, Type = ComparatorType.LessThanOrEqualTo, Name = "halt_no_balance", Value = "0", OutcomeId = 1 //same outcome }; //when account has "allowOverdraft=true" in their Extras var whenAccountHasAllowOverdraftFlag = new Condition { Active = true, ConditionApplicatorType = ConditionApplicatorType.One, AppliedToAccountNumbers = "9237452718263673", ConditionConnector = ConditionConnector.None, Key = ComparatorKey.Custom, KeyExpression = "$.Extra.allowOverdraft", Type = ComparatorType.EqualTo, Name = "halt_no_balance", Value = "true", OutcomeId = 1 //same outcome }; var outcome = new ConditionOutcome { Active = true, OutcomeType = OutcomeType.Halt }; //act var db = new BillingwareDataContext(); db.Conditions.Add(whenRequestIsDebit); db.Conditions.Add(whenAccountHasNoMoney); db.Conditions.Add(whenAccountHasAllowOverdraftFlag); db.Outcomes.Add(outcome); db.SaveChanges(); //assert Assert.True(whenRequestIsDebit.Id > 0); }
public double FuzzyTest(ComparisonContext ctx) { int totalMatch = 0; int lastChildMatchedIndex = 0; int savedContextIndex = 0; bool contextChangeInProgress = false; bool[] currentMatched = new bool[ctx.InstructionList.Count]; bool[] lastCurrentMatched = ctx.AlreadyMatched; ctx.AlreadyMatched = currentMatched; do { int iterationMatch = 0; if (ctx.CurrentIndex >= ctx.InstructionList.Count) { break; } if (Type == NodeType.Leaf) { if (ctx.InstructionList[ctx.CurrentIndex].OpCode == this.Value) { iterationMatch++; ctx.AlreadyMatched[ctx.CurrentIndex] = true; } } else // if (Type == NodeType.Node) { bool contextChanged = false; for (; lastChildMatchedIndex < Childs.Count; lastChildMatchedIndex++) { var v = Childs[lastChildMatchedIndex]; ConditionOutcome outcome = ConditionOutcome.NotMatched; if (Condition != null) { outcome = Condition(ctx, v); } else { outcome = v.Test(ctx); } if (outcome == ConditionOutcome.Matched) { iterationMatch++; if (Mode == TestMode.InRange) { break; } } else if (Mode == TestMode.MatchEverything) { if (!contextChangeInProgress) { savedContextIndex = ctx.CurrentIndex; contextChangeInProgress = true; } if (ctx.CurrentIndex + 1 >= ctx.InstructionList.Count) { ctx.CurrentIndex = savedContextIndex; lastChildMatchedIndex++; break; } ctx.CurrentIndex++; contextChanged = true; break; } } if (contextChanged) { contextChanged = false; continue; } } if (iterationMatch == 0) { break; } totalMatch += iterationMatch; } while ((Type == NodeType.Leaf || Mode == TestMode.InRange) && (!MaxNumber.HasValue || totalMatch < MaxNumber)); // Commit eventually current matched position in the master array // Reason for returning NotMatched: // 1. If this is a Leaf: // 1.1: Matched number less than MinNumber // 2. If this is a Node: // 2.1: Comparison mode is InRange and matching number is outside this range // 2.2: Comparison mode is MatchEverything and not everything is matched if (((Type == NodeType.Leaf || Mode == TestMode.InRange) && totalMatch < MinNumber) || (Mode == TestMode.MatchEverything && totalMatch != Childs.Count)) { //return ConditionOutcome.NotMatched; } //return ConditionOutcome.Matched; return(0); }