public IMarketRuleResultIntent Apply(Fixture fixture, IMarketStateCollection oldState, IMarketStateCollection newState) { var result = new MarketRuleResultIntent(); if (oldState == null) return result; var deletedMarkets = newState.Markets.Select(marketId => newState[marketId]) .Where(marketState => marketState.IsDeleted && oldState.HasMarket(marketState.Id) && !oldState[marketState.Id].IsDeleted) .ToList(); var newDeletedMarketState = deletedMarkets.Select(CreateSuspendedMarket).ToList(); if (deletedMarkets.Any()) { newDeletedMarketState.ForEach(m => { _logger.DebugFormat("market rule={0} => {1} of fixtureId={2} was deleted from UDAPI - it will be suspended", Name, m, fixture.Id); result.AddMarket(m, new MarketRuleAddIntent(MarketRuleAddIntent.OperationType.CHANGE_SELECTIONS)); }); } return result; }
public IMarketRuleResultIntent Apply(Fixture fixture, IMarketStateCollection oldState, IMarketStateCollection newState) { MarketRuleResultIntent intent = new MarketRuleResultIntent(); // only apply delta rule on a full snapshot if (fixture.Tags == null || !fixture.Tags.Any() || oldState == null) return intent; foreach (var mkt in fixture.Markets) { if (oldState.HasMarket(mkt.Id)) { IMarketState state = oldState[mkt.Id]; // do not apply the delta rule on markets which have // been put in a forced suspended state if (state.IsForcedSuspended) continue; if (Severity == DeltaRuleSeverity.REMOVE_SELECTIONS) { ApplyDeltaRule_RemovingSelections(fixture, mkt, state, intent); } else if (Severity == DeltaRuleSeverity.REMOVE_MARKETS) { ApplyDeltaRule_RemovingMarkets(fixture, mkt, state, intent); } } } return intent; }
public IMarketRuleResultIntent Apply(Fixture fixture, IMarketStateCollection oldState, IMarketStateCollection newState) { var result = new MarketRuleResultIntent(); if (!fixture.IsMatchOver || oldState == null) return result; var markets = fixture.Markets.ToDictionary(m => m.Id); // get list of markets which are either no longer in snapshot or are in the snapshot and are not resulted // markets which were already priced (activated) should be ignored var marketsNotPresentInTheSnapshot = new List<IMarketState>(); foreach (var mkt in newState.Markets) { IMarketState mkt_state = newState[mkt]; if (!mkt_state.IsResulted && (!markets.ContainsKey(mkt_state.Id) || !markets[mkt_state.Id].IsResulted)) marketsNotPresentInTheSnapshot.Add(mkt_state); } foreach (var mkt_state in marketsNotPresentInTheSnapshot) { if (mkt_state.HasBeenActive) { _logger.DebugFormat("market rule={0} => marketId={1} of {2} was priced during the fixture lifetime but has NOT been settled on match over.", Name, mkt_state.Id, fixture); continue; } if (!mkt_state.HasBeenProcessed) { _logger.DebugFormat("market rule={0} => marketId={1} of {2} was never passed to the plugin.", Name, mkt_state.Id, fixture); continue; } var market = fixture.Markets.FirstOrDefault(m => m.Id == mkt_state.Id); if (market == null) { _logger.DebugFormat("market rule={0} => marketId={1} of {2} is marked to be voided", Name, mkt_state.Id, fixture); result.AddMarket(CreateSettledMarket(mkt_state), new MarketRuleAddIntent(MarketRuleAddIntent.OperationType.SETTLE_SELECTIONS)); } else { _logger.DebugFormat("market rule={0} => marketId={1} of {2} that was in the snapshot but wasn't resulted is marked to be voided", Name, market.Id, fixture); Action<Market> action = x => x.Selections.ForEach(s => s.Status = SelectionStatus.Void); MarketRuleEditIntent edit = new MarketRuleEditIntent(action, MarketRuleEditIntent.OperationType.CHANGE_SELECTIONS); result.EditMarket(market, edit); } } return result; }
/// <summary> /// /// Remove markets from snapshot/update when: /// current market state is inactive AND the previous state was inactive too (with no change in status or name) /// /// NB: If there is a change in market's name or status then will not be removed /// /// </summary> public IMarketRuleResultIntent Apply(Fixture fixture, IMarketStateCollection oldState, IMarketStateCollection newState) { var result = new MarketRuleResultIntent(); var inactiveMarkets = fixture.Markets.Where( m => (oldState != null && oldState.HasMarket(m.Id) && oldState[m.Id].IsEqualTo(newState[m.Id])) && (!m.IsActive && !oldState[m.Id].IsActive)); foreach (var market in inactiveMarkets.ToList()) { result.MarkAsRemovable(market); _Logger.DebugFormat("market rule={0} => {1} of fixtureId={2} is marked as removable", Name, market, fixture.Id); } return result; }
public void GivenTheMarketRulesReturnTheFollowingIntents(Table table) { MarketRulesManager manager = ScenarioContext.Current["MARKETRULEMANAGER"] as MarketRulesManager; manager.Should().NotBeNull(); Fixture fixture = ScenarioContext.Current["FIXTURE"] as Fixture; fixture.Should().NotBeNull(); foreach (var row in table.Rows) { var name = row["Rule"]; Mock<IMarketRule> rule = ScenarioContext.Current["RULE-" + name] as Mock<IMarketRule>; rule.Should().NotBeNull(); var mkt_name = row["Market"]; var result = row["Result"]; var mkt = fixture.Markets.FirstOrDefault( x => x.Id == mkt_name); mkt.Should().NotBeNull(); if (!ScenarioContext.Current.ContainsKey("INTENT-RULE-" + name)) { MarketRuleResultIntent rule_intent = new MarketRuleResultIntent(); ScenarioContext.Current.Add("INTENT-RULE-" + name, rule_intent); rule.Setup(x => x.Apply(It.IsAny<Fixture>(), It.IsAny<IMarketStateCollection>(), It.IsAny<IMarketStateCollection>())).Returns(rule_intent); } MarketRuleResultIntent intent = ScenarioContext.Current["INTENT-RULE-" + name] as MarketRuleResultIntent; intent.Should().NotBeNull(); switch (result) { case "E": Action<Market> action = x => x.AddOrUpdateTagValue("name", x.Name + " - E: " + name); MarketRuleEditIntent edit_intent = new MarketRuleEditIntent(action, MarketRuleEditIntent.OperationType.CHANGE_DATA); intent.EditMarket(mkt, edit_intent); break; case "!E": intent.MarkAsUnEditable(mkt); break; case "R": intent.MarkAsRemovable(mkt); break; case "!R": intent.MarkAsUnRemovable(mkt); break; case "CS": Action<Market> edit_seln_action = x => x.Selections.ForEach(y => y.Name = y.Name + name); MarketRuleEditIntent change_seln_edit_intent = new MarketRuleEditIntent(edit_seln_action, MarketRuleEditIntent.OperationType.CHANGE_SELECTIONS); intent.EditMarket(mkt, change_seln_edit_intent); break; case "CD": Action<Market> change_data_action = x => x.AddOrUpdateTagValue("name", x.Name + name); MarketRuleEditIntent change_data_edit_intent = new MarketRuleEditIntent(change_data_action, MarketRuleEditIntent.OperationType.CHANGE_DATA); intent.EditMarket(mkt, change_data_edit_intent); break; case "AS": Action<Market> add_seln_action = x => x.Selections.Add(new Selection { Name = mkt.Name + (x.Selections.Count() + 1) + name, Id = mkt.Name + x.Selections.Count() + name }); MarketRuleEditIntent add_seln_intent = new MarketRuleEditIntent(add_seln_action, MarketRuleEditIntent.OperationType.ADD_SELECTIONS); intent.EditMarket(mkt, add_seln_intent); break; case "RS": Action<Market> remove_seln_action = x => x.Selections.Clear(); MarketRuleEditIntent remove_seln_intent = new MarketRuleEditIntent(remove_seln_action, MarketRuleEditIntent.OperationType.REMOVE_SELECTIONS); intent.EditMarket(mkt, remove_seln_intent); break; default: throw new Exception("Unknow status"); } } }
public IMarketRuleResultIntent Apply(Fixture fixture, IMarketStateCollection oldState, IMarketStateCollection newState) { var result = new MarketRuleResultIntent(); if (_includedSports.Contains(newState.Sport.ToLower())) { foreach (var mkt in fixture.Markets) { string type = string.Format("{0}.{1}", newState.Sport, mkt.Type).ToLower(); if (_excludedMarketTypes.Contains(type)) { _Logger.DebugFormat("market rule={0} => {1} of {2} is excluded from rule due its type={3}", Name, mkt, fixture, mkt.Type); continue; } var oldMarketState = oldState != null ? oldState[mkt.Id] : null; var newMarketState = newState[mkt.Id]; if (oldMarketState == null) { //must be a snapshot then if (newMarketState.IsActive) { //create market _Logger.DebugFormat("market rule={0} => {1} of {2} is created", Name, mkt, fixture); result.MarkAsUnRemovable(mkt); } else { //dont create market _Logger.DebugFormat("market rule={0} => {1} of {2} is not created", Name, mkt, fixture); result.MarkAsRemovable(mkt); } } else { if (oldMarketState.HasBeenActive) continue; if (newMarketState.IsActive) { //create Action<Market> editMarketAction = (m => { if (newMarketState.TagsCount == 0) return; foreach (var tagKey in newMarketState.TagKeys) { m.AddOrUpdateTagValue(tagKey, newMarketState.GetTagValue(tagKey)); } foreach (var sel in m.Selections) { var selState = newMarketState[sel.Id]; foreach (var tagKey in selState.TagKeys) { sel.AddOrUpdateTagValue(tagKey, selState.GetTagValue(tagKey)); } } }); var mri = new MarketRuleEditIntent(editMarketAction, MarketRuleEditIntent.OperationType.CHANGE_DATA); _Logger.DebugFormat("market rule={0} => {1} of {2} is created", Name, mkt, fixture); result.EditMarket(mkt, mri); } else { //dont create market _Logger.DebugFormat("market rule={0} => {1} of {2} is not created", Name, mkt, fixture); result.MarkAsRemovable(mkt); } } } } return result; }
public void PostRuleProcessingTest() { // This test sets up a dummy market rule that removes // all the markets whose Id start with "REMOVE". // The test, after calling ApplyRules() on the MarketRuleManager // checks if the property "HasBeenProcessed" is set to true // for all the markets whose Id don't start with REMOVE. // // The HasBeenProcessed property is set to true only // when a market has been passed at least once to the // plugin, or in other words, the outcome of the // MarketRuleManager hasn't remove it from the Fixture object. // This property is set on IUpdatableMarketState.ApplyPostRulesProcessing() Mock<IMarketRule> aRule = new Mock<IMarketRule>(); aRule.Setup(x => x.Apply(It.IsAny<Fixture>(), It.IsAny<IMarketStateCollection>(), It.IsAny<IMarketStateCollection>())) .Returns((Fixture f, IMarketStateCollection nS, IMarketStateCollection oS) => { MarketRuleResultIntent intent = new MarketRuleResultIntent(); foreach(var mkt in f.Markets) { if(mkt.Id.StartsWith("REMOVE")) intent.MarkAsRemovable(mkt); } return intent; } ); var settings = new Mock<ISettings>(); var plugin = new Mock<IAdapterPlugin>(); var stateprovider = new StateManager(settings.Object, plugin.Object); List<IMarketRule> rules = new List<IMarketRule> { aRule.Object }; Fixture fixture = new Fixture { Id = "ABC", MatchStatus = "30"}; Market testMkt = new Market { Id = "1"}; fixture.Markets.Add(testMkt); testMkt = new Market { Id = "REMOVE-1" }; fixture.Markets.Add(testMkt); testMkt = new Market { Id = "2" }; fixture.Markets.Add(testMkt); testMkt = new Market { Id = "REMOVE-2" }; fixture.Markets.Add(testMkt); MarketRulesManager manager = new MarketRulesManager(fixture.Id, stateprovider, rules); manager.ApplyRules(fixture); manager.CurrentState["1"].Should().NotBeNull(); manager.CurrentState["1"].HasBeenProcessed.Should().BeTrue(); manager.CurrentState["2"].Should().NotBeNull(); manager.CurrentState["2"].HasBeenProcessed.Should().BeTrue(); manager.CurrentState["REMOVE-1"].Should().NotBeNull(); manager.CurrentState["REMOVE-1"].HasBeenProcessed.Should().BeFalse(); manager.CurrentState["REMOVE-2"].Should().NotBeNull(); manager.CurrentState["REMOVE-2"].HasBeenProcessed.Should().BeFalse(); manager.CommitChanges(); manager.CurrentState["1"].Should().NotBeNull(); manager.CurrentState["1"].HasBeenProcessed.Should().BeTrue(); manager.CurrentState["2"].Should().NotBeNull(); manager.CurrentState["2"].HasBeenProcessed.Should().BeTrue(); manager.CurrentState["REMOVE-1"].Should().NotBeNull(); manager.CurrentState["REMOVE-1"].HasBeenProcessed.Should().BeFalse(); manager.CurrentState["REMOVE-2"].Should().NotBeNull(); manager.CurrentState["REMOVE-2"].HasBeenProcessed.Should().BeFalse(); }
/// <summary> /// This execution of the delta rule CAN remove single selections /// from a market if they haven't changes since last time. /// </summary> /// <param name="fixture"></param> /// <param name="mkt"></param> /// <param name="state"></param> /// <param name="intent"></param> private void ApplyDeltaRule_RemovingSelections(Fixture fixture, Market mkt, IMarketState state, MarketRuleResultIntent intent) { List<Selection> seln_changed = new List<Selection>(); foreach (var seln in mkt.Selections) { // if we don't have the selection state, we can't // determine what has changed within the selection, // so we assume that everything has changed if (state.HasSelection(seln.Id) && state[seln.Id].IsEquivalentTo(seln, true)) continue; _logger.DebugFormat("market rule={0} => {1} of {2} has changed", Name, seln, mkt); seln_changed.Add(seln); } if (seln_changed.Count == 0) { if (state.IsEquivalentTo(mkt, true, false)) { _logger.DebugFormat("market rule={0} => {1} of {2} marked as removable", Name, mkt, fixture); intent.MarkAsRemovable(mkt); } else { Action<Market> action = x => x.Selections.Clear(); MarketRuleEditIntent edit = new MarketRuleEditIntent(action, MarketRuleEditIntent.OperationType.REMOVE_SELECTIONS); intent.EditMarket(mkt, edit); } } else { if (seln_changed.Count() != mkt.Selections.Count()) { Action<Market> action = x => x.Selections.RemoveAll(y => !seln_changed.Contains(y)); MarketRuleEditIntent edit = new MarketRuleEditIntent(action, MarketRuleEditIntent.OperationType.REMOVE_SELECTIONS); intent.EditMarket(mkt, edit); } } }
/// <summary> /// This execution of the delta rule can only remove markets from the fixture. /// This is different from ApplyDeltaRule_RemovingSelections where selections can /// be removed from markets. /// /// A market is then removed from a fixture if either its tags and all its selections /// haven't changed since last time. /// /// If only a selection has changed, then entire market, with the remaining selections, /// remains untouched by the delta rule. /// </summary> /// <param name="fixture"></param> /// <param name="mkt"></param> /// <param name="state"></param> /// <param name="intent"></param> private void ApplyDeltaRule_RemovingMarkets(Fixture fixture, Market mkt, IMarketState state, MarketRuleResultIntent intent) { if (state.IsEquivalentTo(mkt, true, true)) { intent.MarkAsRemovable(mkt); _logger.DebugFormat("market rule={0} => {1} of {2} marked as removable", Name, mkt, fixture); } }