public void MarkAsUnRemovable(Market market)
        {
            if (market == null || _unRemovables.Contains(market))
                return;

            _unRemovables.Add(market);
        }
        private void SetSelectionIds(Market firstMarket, Market currentMarketIndex, string selectionIndexTag)
        {
            foreach (var selection in currentMarketIndex.Selections)
            {
                // tag selection matching by tags
                var matchingSelection = firstMarket.Selections.First(s => s.Tags.All(tag => TagEquals(selectionIndexTag, tag, selection)));

                _selections[selection.Id] = matchingSelection.Id;
            }
        }
        public void WhenUpdateArrives(Table table)
        {
            var market = new Market {Id = "TestId"};
            market.AddOrUpdateTagValue("name", "TestMarket");
            market.Selections.Clear();
            market.Selections.AddRange(table.Rows.Select(r=>  Helper.GetObjectFromTableRow<Selection>(r)));

            _fixture.Markets.Clear();
            _fixture.Markets.Add(market);            
        }
        public void GivenIHaveThisMarket(Table table)
        {
            Market market = new Market();
            market.Id = "ABC";
            if (table.Rows.Count > 0)
                market.Id = table.Rows[0]["Value"];

            if (ScenarioContext.Current.ContainsKey("Market"))
                ScenarioContext.Current.Remove("Market");

            ScenarioContext.Current.Add("Market", market);
        }
        public IndexMapping(Market firstMarket, Market firstActiveMarket, Market currentMarketIndex, int index, string nextMarketId, string selectionIndexTag, string marketName)
        {
            Index = index;
            MarketId = firstMarket.Id;
            NextMarketId = nextMarketId;
            MarketName = marketName;

            if (firstActiveMarket.Id == currentMarketIndex.Id)
                IsCurrent = true;

            SetSelectionIds(firstMarket, currentMarketIndex, selectionIndexTag);
        }
        private static Market CreateSuspendedMarket(IMarketState MarketState)
        {

            var market = new Market(MarketState.Id) {IsSuspended = true};

            if (MarketState.HasTag("line"))
            {
                market.AddOrUpdateTagValue("line", MarketState.GetTagValue("line"));
            }

            foreach (var stateSelection in MarketState.Selections)
                market.Selections.Add(new Selection { Id = stateSelection.Id, Status = SelectionStatus.Pending, Tradable = false, Price = 0 });

            return market;
        }
        public void AddMarket(Market market, MarketRuleAddIntent addIntent)
        {
            if (market == null || _added.ContainsKey(market))
                return;

            _added.Add(market,addIntent);
        }
        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();
        }
        public void SuspendFixtureOnStreamListenerDisposeTest()
        {
            // STEP 1: prepare stub data
            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            Mock<ISettings> settings = new Mock<ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);

            provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendInPlayMarketsStrategy, SuspensionReason.DISCONNECT_EVENT);

            // STEP 3: prepare the fixture data
            Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() };
            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            fixture.Markets.Add(new Market("MKT-1"));
            var mkt = new Market("MKT-2");
            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);


            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            connector.Verify(x => x.ProcessStreamUpdate(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never);

            listener.Dispose();

            connector.Verify(x=> x.Suspend(It.IsAny<string>()),Times.Once);

            //// STEP 5: check the result, note tha MKT-2 is not in-play
            //connector.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>(
            //    y => y.Id == "ABC" &&
            //         y.Markets.Count == 1 &&
            //         y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null),
            //    It.IsAny<bool>()), Times.Once);

        }
        public void DontSendSuspensionOnDisposingIfFixtureEndedOrDeletedTest()
        {
            // STEP 1: prepare data

            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            
            var provider = new StateManager(_settings.Object, connector.Object);

            bool disposed = false;
            bool matchover = false;
            bool deleted = false;

            Action<IMarketStateCollection> disponsing_strategy = x => {disposed = true;};
            Action<IMarketStateCollection> matchover_strategy = x => { matchover = true; };
            Action<IMarketStateCollection> deleted_strategy = x => { deleted = true; };

            provider.SuspensionManager.RegisterAction(disponsing_strategy, SuspensionReason.FIXTURE_DISPOSING);
            provider.SuspensionManager.RegisterAction(deleted_strategy, SuspensionReason.FIXTURE_DELETED);
            provider.SuspensionManager.RegisterAction(matchover_strategy, SuspensionReason.SUSPENSION);
           

            Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 };

            Market mkt = new Market { Id = "MKT" };

            fixture.Markets.Add(mkt);

            Fixture update = new Fixture
            {
                Id = "ABCDE",
                Sequence = 2,
                MatchStatus = ((int)MatchStatus.InRunning).ToString(),
                Epoch = 2,
                LastEpochChangeReason = new[] { (int)EpochChangeReason.Deleted }
            };

            StreamMessage message = new StreamMessage { Content = update };

            resource.Setup(x => x.Id).Returns("ABCDE");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 2: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            disposed.Should().BeFalse();
            matchover.Should().BeFalse();
            deleted.Should().BeFalse();

            // STEP 3: send a delete command and check the result
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));

            //Update snapshot sequence
            fixture.Sequence = 2;
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            disposed.Should().BeFalse();
            matchover.Should().BeFalse();
            deleted.Should().BeTrue();

            // STEP 4: reset the flags and send the dispose command
            // (no other suspension commands should be raised);
            disposed = false;
            matchover = false;
            deleted = false;

            listener.Dispose();

            deleted.Should().BeFalse();
            disposed.Should().BeFalse();
            matchover.Should().BeFalse();

            // STEP 5: do the same, but for MatchOver 
            disposed = false;
            matchover = false;
            deleted = false;

            listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            disposed.Should().BeFalse();
            matchover.Should().BeFalse();
            deleted.Should().BeFalse();

            update = new Fixture
            {
                Id = "ABCDE",
                Sequence = 2,
                MatchStatus = ((int)MatchStatus.MatchOver).ToString(),
                Epoch = 2,
                LastEpochChangeReason = new[] { (int)EpochChangeReason.MatchStatus }
            };

            message = new StreamMessage { Content = update };

            // STEP 3: send a delete command and check the result
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));

            disposed.Should().BeFalse();
            matchover.Should().BeTrue();
            deleted.Should().BeFalse();

            // STEP 4: reset the flags and send the dispose command
            // (no other suspension commands should be raised);
            disposed = false;
            matchover = false;
            deleted = false;

            listener.Dispose();

            deleted.Should().BeFalse();
            disposed.Should().BeFalse();
            matchover.Should().BeFalse();
        }
        private void MergeSelectionStates(Market market, bool fullSnapshot)
        {
            if (market.Selections == null)
                return;

            foreach (var selection in market.Selections)
            {
                if (_selectionStates.ContainsKey(selection.Id))
                    _selectionStates[selection.Id].Update(selection, fullSnapshot);
                else
                {
                    _selectionStates[selection.Id] = new SelectionState(selection, fullSnapshot);
                }
            }
        }
        private void UpdateLineOnRollingHandicap(Market market)
        {
            var rollingHandicap = market as RollingMarket;
            if (rollingHandicap == null)
                return;

            var oneLine = _selectionStates.Values.All(s => s.Line == _selectionStates.Values.First().Line);

            if (oneLine)
                rollingHandicap.Line = rollingHandicap.Selections.First().Line;
            else
            {
                var selectionWithHomeTeam =
                    _selectionStates.Values.FirstOrDefault(s => s.HasTag("team") && s.GetTagValue("team") == "1");
                if (selectionWithHomeTeam == null)
                    throw new ArgumentException(string.Format("Rolling handicap line for market {0} can't be verified", market));

                var homeSelection = rollingHandicap.Selections.FirstOrDefault(s => s.Id == selectionWithHomeTeam.Id);

                //during update we may not receive an update for all selections
                if (homeSelection != null)
                {
                    rollingHandicap.Line = homeSelection.Line;
                }
                else
                {
                    var selectionWithAwayTeam =
                        _selectionStates.Values.FirstOrDefault(s => s.HasTag("team") && s.GetTagValue("team") == "2");

                    // invert the line
                    rollingHandicap.Line = selectionWithAwayTeam.Line * (-1);
                }
            }

            this.Line = rollingHandicap.Line;
        }
        public void Update(Market market, bool fullSnapshot)
        {

            MergeSelectionStates(market, fullSnapshot);

            if (fullSnapshot)
            {
                _tags = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
                foreach (var key in market.TagKeys)
                    _tags.Add(key, market.GetTagValue(key));

                if (_tags.ContainsKey("traded_in_play"))
                    IsTradedInPlay = string.Equals(_tags["traded_in_play"], "true", StringComparison.InvariantCultureIgnoreCase);
            }
            
            // always set to false at each update
            IsForcedSuspended = false;

            market.IsPending = IsPending;
            market.IsActive = IsActive;
            market.IsResulted = IsResulted;
            market.IsSuspended = IsSuspended;
            market.IsTradedInPlay = IsTradedInPlay;
            market.IsVoided = IsVoided;

            UpdateLineOnRollingHandicap(market);
        }
        public bool IsEquivalentTo(Market market, bool checkTags, bool checkSelections)
        {
            if (market == null)
                return false;

            if (market.Id != Id)
                return false;

            if(checkTags)
            {
                if (market.TagsCount != TagsCount)
                    return false;

                if (market.TagKeys.Any(tag => !HasTag(tag) || GetTagValue(tag) != market.GetTagValue(tag)))
                    return false;
            }

            if (checkSelections)
            {
                if (Selections.Count() != market.Selections.Count())
                    return false;

                foreach (var seln in market.Selections)
                {
                    ISelectionState seln_state = this[seln.Id];
                    if (seln_state == null)
                        return false;

                    if (!seln_state.IsEquivalentTo(seln, checkTags))
                        return false;
                }
            }

            var result = IsSuspended == market.IsSuspended &&
                         IsActive == market.IsActive &&
                         IsResulted == market.IsResulted &&
                         IsPending == market.IsPending &&
                         IsVoided == market.IsVoided;


            if (IsRollingMarket)
                result &= Line == ((RollingMarket)market).Line;

            // the only case we really should pay attention
            // is when we have forced the suspension
            // when the market was active
            if(IsForcedSuspended)
                result &= market.IsSuspended;
            
            return result;
        }
        public void UnsuspendFixtureAndMarketsTest()
        {
            // STEP 1: prepare stub data
            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            Mock<ISettings> settings = new Mock<ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);

            provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendInPlayMarketsStrategy, SuspensionReason.DISCONNECT_EVENT);

            // STEP 2: prepare the fixture data
            Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() };
            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            var mkt1 = new Market { Id = "MKT-1" };
            mkt1.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active, Tradable = true });
            fixture.Markets.Add(mkt1);

            var mkt = new Market("MKT-2");
            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);
            
            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary() { Sequence = 1 } );
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();
            
            connector.Verify(x => x.ProcessStreamUpdate(It.IsAny<Fixture>(), It.IsAny<bool>()), Times.Never);

            listener.Dispose();

            
            //Should suspend at the fixture level only
            connector.Verify(x=> x.Suspend(It.Is<string>(fId => fId == "ABC")),Times.Once);
            

            //recreate listener
            //must have state setup otherwise it will process snapshot not unsuspend
            state.Setup(x => x.GetFixtureState(It.Is<string>(fId => fId == fixture.Id)))
                .Returns(new FixtureState()
                {
                    Id = fixture.Id,
                    MatchStatus = MatchStatus.InRunning,
                    Sequence = fixture.Sequence
                });

            listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);
            listener.Start();

            // Unsuspend should be called on reconnect 
            connector.Verify(x => x.UnSuspend(It.IsAny<Fixture>()),Times.Once);

        }
        public void SuspensionManagerStrategiesTest()
        {
            var stateProvider = new Mock<IStateProvider>();
            var plugin = new Mock<IAdapterPlugin>();
            var suspensionManager = new SuspensionManager(stateProvider.Object, plugin.Object);

            var state = new MarketStateCollection("FXT-ID");

            // STEP 1: prepare the fixture 
            // 1) fixture is in running
            // 2) with 2 in play markets
            // 3) 1 not in-play market
            // 4) 3 markets with an unknown state
            Fixture fixture = new Fixture
            {
                Id = "FXT-ID",
                MatchStatus = MatchStatus.InRunning.ToString(),
                Sequence = 2
            };

            var mkt1 = new Market { Id = "MKT-1" };
            mkt1.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active });

            var mkt2 = new Market { Id = "MKT-2" };
            mkt2.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active });

            var mkt3 = new Market { Id = "MKT-3" };
            mkt3.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Pending });

            var mkt4 = new Market { Id = "MKT-4" };
            mkt4.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active });
            mkt4.AddOrUpdateTagValue("traded_in_play", "false");

            var mkt5 = new Market { Id = "MKT-5" };
            mkt5.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active });
            mkt5.AddOrUpdateTagValue("traded_in_play", "true");

            var mkt6 = new Market { Id = "MKT-6" };
            mkt6.AddOrUpdateTagValue("traded_in_play", "true");

            fixture.Markets.Add(mkt1);
            fixture.Markets.Add(mkt2);
            fixture.Markets.Add(mkt3);
            fixture.Markets.Add(mkt4);
            fixture.Markets.Add(mkt5);
            fixture.Markets.Add(mkt6);
            state.Update(fixture, true);
            
            state.CommitChanges();
            
            // STEP 2: test the suspension strategies
            suspensionManager.SuspendAllMarketsStrategy(state);

            plugin.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>
                (
                    y => y.Markets.Count == 6 &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-2") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-3") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-4") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-5") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-6") != null
                ), It.IsAny<bool>()));


            suspensionManager.SuspendFixtureIfInPlayStrategy(state);

            plugin.Verify(x => x.Suspend(It.Is<string>(y => y == "FXT-ID")));

            suspensionManager.SuspendFixtureStrategy(state);

            plugin.Verify(x => x.Suspend(It.Is<string>(y => y == "FXT-ID")));

            suspensionManager.SuspendInPlayMarketsStrategy(state);

            // The SuspensionManager takes a conservative approach.
            // If the traded_in_play tag is not present, it assumes
            // that the market is a in-play market
            plugin.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>
                (
                    y => y.Markets.Count == 3 &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-2") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-3") == null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-4") == null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-5") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-6") == null
                ), It.IsAny<bool>()));


            // STEP 3: change the fixture
            // 1) change the fixture's match status
            // 2) remove a mkt
            // 3) add a new mkt

            fixture.MatchStatus = MatchStatus.MatchOver.ToString();

            fixture.Markets.Remove(fixture.Markets.FirstOrDefault(x => x.Id == "MKT-5"));

            var mkt7 = new Market { Id = "MKT-7" };
            mkt7.Selections.Add(new Selection { Id = "SELN", Status = SelectionStatus.Active });
            mkt7.AddOrUpdateTagValue("traded_in_play", "true");

            fixture.Markets.Add(mkt7);

            state.Update(fixture, true);
            state.CommitChanges();
            
            // STEP 4: test the suspension strategies again
            suspensionManager.SuspendAllMarketsStrategy(state);

            // note that we must have 7 markets now because the 
            // SuspensionManager looks at the MarketState, not
            // at the fixture
            plugin.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>
                (
                    y => y.Markets.Count == 7 &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-2") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-3") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-4") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-5") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-6") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-7") != null 
                ), It.IsAny<bool>()));


            suspensionManager.SuspendFixtureIfInPlayStrategy(state);

            // The fixture is "MatchOver", so the Suspend() method should not have been called
            // Times.Exactly(2) because it has been called in the previous step...unfortunately
            // there seems to be no way to reset the verifications
            plugin.Verify(x => x.Suspend(It.Is<string>(y => y == "FXT-ID")), Times.Exactly(2));

            suspensionManager.SuspendFixtureStrategy(state);

            plugin.Verify(x => x.Suspend(It.Is<string>(y => y == "FXT-ID")), Times.Exactly(3));

            suspensionManager.SuspendInPlayMarketsStrategy(state);

            plugin.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>
                (
                    y => y.Markets.Count == 4 &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-2") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-3") == null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-4") == null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-5") != null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-6") == null &&
                         y.Markets.FirstOrDefault(z => z.Id == "MKT-7") != null
                ), It.IsAny<bool>()));

        }
        public void MarkFixtureAsUnpublishedTest()
        {
            // STEP 1: prepare the stub data
            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            
            _settings.Setup(x => x.DeltaRuleEnabled).Returns(true);
            var provider = new StateManager(_settings.Object, connector.Object);

            //var suspended = false;
            //Action<IMarketStateCollection> suspension_strategy = x => {suspended = true;};
            //suspension.RegisterAction(suspension_strategy, SuspensionReason.FIXTURE_DELETED);

            // Please note Sequence = 1
            Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 };

            Market mkt = new Market { Id = "MKT" };

            fixture.Markets.Add(mkt);

            // ...and Sequence = 3
            Fixture update = new Fixture
            {
                Id = "ABCDE",
                Sequence = 2,
                MatchStatus = ((int)MatchStatus.MatchOver).ToString(), 
                Epoch = 2, 
                LastEpochChangeReason = new [] {(int)EpochChangeReason.Deleted}
            };

            StreamMessage message = new StreamMessage { Content = update };

            resource.Setup(x => x.Id).Returns("ABCDE");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 2: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, _settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            // STEP 3: let create at lea
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));

            connector.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>(y => y.Markets.All(k => k.IsSuspended)), It.IsAny<bool>()));

            update = new Fixture
            {
                Id = "ABCDE",
                Sequence = 3,
                MatchStatus = ((int)MatchStatus.MatchOver).ToString(), 
                Epoch = 2
            };

            mkt = new Market {Id = "MKT"};

            update.Markets.Add(mkt);

            update.Tags.Add("tag", "tag");

            message = new StreamMessage { Content = update };

            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));

            // STEP 4: if the delta rule was executed, the market would have been removed
            fixture.Markets.FirstOrDefault(x => x.Id == "MKT").Should().NotBeNull();
        }
 public MarketState(Market market, bool fullSnapshot)
     : this(market.Id)
 {
     IsRollingMarket = market is RollingMarket;
     this.Update(market, fullSnapshot);                
 }
        public void MarkMarkedAsForcedSuspended()
        {
            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            
            _settings.Setup(x => x.DeltaRuleEnabled).Returns(true);
            var provider = new StateManager(_settings.Object, connector.Object);
            
            provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendAllMarketsStrategy, SuspensionReason.SUSPENSION);

            //var suspended = false;
            //Action<IMarketStateCollection> suspension_strategy = x => {suspended = true;};
            //suspension.RegisterAction(suspension_strategy, SuspensionReason.FIXTURE_DELETED);

            // Please note Sequence = 1
            Fixture fixture = new Fixture { Id = "ABCDE", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString(), Epoch = 1 };

            Market mkt = new Market { Id = "MKT" };

            fixture.Markets.Add(mkt);

            // ...and Sequence = 3
            Fixture update = new Fixture
            {
                Id = "ABCDE",
                Sequence = 2,
                MatchStatus = ((int)MatchStatus.MatchOver).ToString(),
                Epoch = 2,
                LastEpochChangeReason = new[] { (int)EpochChangeReason.BaseVariables }
            };

            StreamMessage message = new StreamMessage { Content = update };

            resource.Setup(x => x.Id).Returns("ABCDE");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 2: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider,_settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();


            //Update snapshot sequence
            fixture.Sequence = 2;
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 3: let create at lea
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));

            var fixtureState = provider.CreateNewMarketRuleManager("ABCDE").CurrentState;
            fixtureState.Markets.All(x => fixtureState[x].IsForcedSuspended).Should().BeFalse();
        }
        private void AddMarket(Fixture snapshot)
        {
            var selections = new List<Selection>
            {
                new Selection {Id = "Sel1", Status = "1", Price = 0.45, Name = "Sel 1", Tradable = false},
                new Selection {Id = "Sel2", Status = "1", Price = 0.45, Name = "Sel 2", Tradable = false},
                new Selection {Id = "Sel3", Status = "1", Price = 0.45, Name = "Sel 3", Tradable = false}
            };

            var market = new Market("testMarketId");
            market.Selections.AddRange(selections);

            snapshot.Markets.Add(market);
        }
        private static Market CreateSettledMarket(IMarketState MarketState)
        {
            var market = new Market (MarketState.Id);

            if (MarketState.HasTag("line"))
            {
                market.AddOrUpdateTagValue("line", MarketState.GetTagValue("line"));
            }

            foreach (var seln in MarketState.Selections)
                market.Selections.Add(new Selection { Id = seln.Id, Status = SelectionStatus.Void, Price = 0 });

            return market;
        }
示例#22
0
        public void SerializeModelTest()
        {

            Fixture fixture = new Fixture
            {
                FixtureName = "TEST-NAME",
                Epoch = 10,
                LastEpochChangeReason = new[] { 10, 20 },
                Id = "TEST-ID",
                StartTime = new DateTime(2000, 01, 01),
                Sequence = 12,
                MatchStatus = "40"
            };
            fixture.Tags.Add("TEST-TAG-1", "1");
            fixture.Tags.Add("TEST-TAG-2", 2);
            fixture.GameState.Add("TEST-STATE-1", 1);
            fixture.GameState.Add("TEST-STATE-2", "2");

            Participant p1 = new Participant { Id = 1, Name = "P1" };
            p1.Tags.Add("TEST-TAG-1", "1");
            p1.Tags.Add("TEST-TAG-2", 2);

            Participant p2 = new Participant { Id = 2, Name = "P2" };

            fixture.Participants.Add(p1);
            fixture.Participants.Add(p2);

            Market mkt1 = new Market { Id = "MKT1" };
            mkt1.AddOrUpdateTagValue("name", "MKT1");

            Selection seln1 = new Selection
            {
                Id = "SELN1",
                Price = 2.0,
                Status = SelectionStatus.Active,
                Tradable = false
            };
            seln1.AddOrUpdateTagValue("name", "seln1");
            seln1.AddOrUpdateTagValue("displayed", "true");

            Selection seln2 = new Selection
            {
                Id = "SELN2",
                Price = 3.0,
                Status = SelectionStatus.Pending,
                Tradable = true
            };
            seln2.AddOrUpdateTagValue("name", "seln2");
            seln2.AddOrUpdateTagValue("displayed", "false");

            mkt1.Selections.Add(seln1);
            mkt1.Selections.Add(seln2);

            RollingMarket mkt2 = new RollingMarket { Id = "RMKT2", Line = 2.0 };
            mkt2.AddOrUpdateTagValue("name", "RMKT2");

            RollingSelection seln3 = new RollingSelection
            {
                Id = "SELN3",
                Price = 7.0,
                Status = SelectionStatus.Pending,
                Tradable = true,
                Line = 21
            };

            ((Market)mkt2).Selections.Add(seln3);
            Market test2 = mkt2;
            test2.Selections.Count.Should().Be(1);
            (test2.Selections.FirstOrDefault() is RollingSelection).Should().BeTrue();

            Market mkt3 = new RollingMarket();
            mkt3.Id = "RMKT3";
            mkt3.AddOrUpdateTagValue("name", "RMKT3");

            fixture.Markets.Add(mkt1);
            fixture.Markets.Add(mkt2);
            fixture.Markets.Add(mkt3);

            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "MKT1").Should().BeNull();
            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "RMKT2").Should().NotBeNull();
            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "RMKT3").Should().NotBeNull();

            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "MKT1").Should().NotBeNull();
            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "RMKT2").Should().BeNull();
            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "RMKT3").Should().BeNull();

            string value = FixtureJsonHelper.ToJson(fixture);
            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)))
            {

                stream.Position = 0;
                string value2 = Encoding.UTF8.GetString(stream.ToArray());

                value.Should().BeEquivalentTo(value2);

                fixture = FixtureJsonHelper.GetFromJson(value2);
            }

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);

            BinaryStoreProvider<Fixture> provider = new BinaryStoreProvider<Fixture>(".", "test-{0}.dat");

            provider.SetObject("TEST", fixture);

            fixture = provider.GetObject("TEST");

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);

            fixture = value.FromJson<Fixture>();

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);
        }
        public void EditMarket(Market market, MarketRuleEditIntent action)
        {
            if (market == null || _edited.ContainsKey(market) || action == null)
                return;

            _edited[market] = action;
        }
        public void DoNotSuspendFixtureOnDisconeectIfDeletedTest()
        {
            // STEP 1: prepare stub data
            Mock<IResourceFacade> resource = new Mock<IResourceFacade>();
            Mock<IAdapterPlugin> connector = new Mock<IAdapterPlugin>();
            Mock<IEventState> state = new Mock<IEventState>();
            Mock<ISettings> settings = new Mock<ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);


            // STEP 3: prepare the fixture data
            Fixture fixture = new Fixture { Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString() };
            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            fixture.Markets.Add(new Market("MKT-1"));
            var mkt = new Market("MKT-2");
            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);

            // ...and MatchStatus=MatchOver
            Fixture update = new Fixture
            {
                Id = "ABC",
                Sequence = 2,
                MatchStatus = ((int)MatchStatus.InRunning).ToString(),
                Epoch = 2,
                LastEpochChangeReason = new[] {(int)EpochChangeReason.Deleted}
            };

            StreamMessage message = new StreamMessage { Content = update };


            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            // STEP 5: send the update
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));


            // STEP 6: check the result, note tha MKT-2 is not in-play
            connector.Verify(x => x.ProcessStreamUpdate(It.Is<Fixture>(y => y.Id == "ABC" && y.Markets.Count == 0), It.IsAny<bool>()));

        }
示例#25
0
        public void SelectionResulStateTest()
        {
            Market mkt = new Market("123");

            var seln = new Selection()
            {
                Id = "A1",
                Result = new Result()
                {
                    StakeParticipants = 1,
                    StakePlaces = 2,
                    WinParticipants = 3,
                    WinPlaces = 4
                }
            };

            mkt.Selections.Add(seln);

            Fixture fxt = new Fixture()
            {
                Id = "FXT",
                FixtureName = "TestSelectionResultTest",
                MatchStatus = "40",
            };

            fxt.Markets.Add(mkt);

            MarketStateCollection collection = new MarketStateCollection("FXT");
            collection.Update(fxt, true);

            var model = collection["123"]["A1"].Result as SelectionResultState;
            model.Should().NotBeNull();

            model.IsEquivalentTo(seln.Result).Should().BeTrue();

            var clone = model.Clone();
            model.IsEqualTo(clone).Should().BeTrue();

            seln.Result.WinParticipants = 2;
            model.IsEquivalentTo(seln.Result).Should().BeFalse();

        }
 public MarketRuleEditIntent GetEditingAction(Market market)
 {
     return _edited.ContainsKey(market) ? _edited[market] : null;
 }
        public void GivenAFixtureWithTheFollowingMarkets(Table table)
        {
            ScenarioContext.Current.Clear();

            Fixture fixture = new Fixture { Id = "Test", MatchStatus = "40" };
            ScenarioContext.Current.Add("FIXTURE", fixture);

            foreach (var row in table.Rows)
            {
                Market mkt = new Market {Id = row["Market"]};
                mkt.AddOrUpdateTagValue("name", row["Name"]);

                fixture.Markets.Add(mkt);

                if (table.ContainsColumn("Selections"))
                {
                    int seln_count = Convert.ToInt32(row["Selections"]);
                    for (int i = 0; i < seln_count; i++)
                    {
                        Selection seln = new Selection { Name = row["Name"] + (i + 1) };
                        seln.Id = seln.Name;
                        mkt.Selections.Add(seln);
                    }
                }
            }
        }
 public MarketRuleAddIntent GetAddAction(Market mkt)
 {
     return _added[mkt];
 }
        private static Market CreateMarket(IMarketState marketState,bool isSuspended = true)
        {
            var market = new Market(marketState.Id) { IsSuspended = isSuspended };
            foreach (var seln in marketState.Selections)
                market.Selections.Add(new Selection { Id = seln.Id, Status = SelectionStatus.Pending, Tradable = !isSuspended });

            return market;
        }
        public void DeltaRuleWithMarketSeverity()
        {
            // STEP 1: prepare stub data
            var settings = new Mock<ISettings>();
            var plugin = new Mock<IAdapterPlugin>();
            var stateprovider = new StateManager(settings.Object, plugin.Object);

            DeltaRule.Instance.Severity = DeltaRule.DeltaRuleSeverity.REMOVE_MARKETS;

            List<IMarketRule> rules = new List<IMarketRule> { DeltaRule.Instance };

            // STEP 2: prepare fixture data
            // Fixture
            //  - MKT1
            //  -- SELN_1_1
            //  -- SELN_1_2
            //  - MKT2
            //  -- SELN_2_1
            //  -- SELN_2_2

            Fixture fixture = new Fixture { Id = "TestId", MatchStatus = "40" };
            fixture.Tags.Add("Sport", "Football");

            Market mkt = new Market { Id = "MKT1" };
            mkt.AddOrUpdateTagValue("name", "mkt1");
            mkt.AddOrUpdateTagValue("type", "type1");

            Selection seln = new Selection { Id = "SELN_1_1" };
            seln.AddOrUpdateTagValue("name", "seln_1_1");
            seln.Tradable = true;
            seln.Status = SelectionStatus.Active;
            seln.Price = 0.1;

            mkt.Selections.Add(seln);

            seln = new Selection { Id = "SELN_1_2" };
            seln.AddOrUpdateTagValue("name", "seln_1_2");
            seln.Tradable = true;
            seln.Status = SelectionStatus.Active;
            seln.Price = 0.2;

            mkt.Selections.Add(seln);

            fixture.Markets.Add(mkt);

            mkt = new Market { Id = "MKT2" };
            mkt.AddOrUpdateTagValue("name", "mkt2");
            mkt.AddOrUpdateTagValue("type", "type2");

            seln = new Selection { Id = "SELN_2_1" };
            seln.AddOrUpdateTagValue("name", "seln_2_1");
            seln.Tradable = false;
            seln.Status = SelectionStatus.Pending;
            seln.Price = null;

            mkt.Selections.Add(seln);

            seln = new Selection { Id = "SELN_2_2" };
            seln.AddOrUpdateTagValue("name", "seln_2_2");
            seln.Tradable = false;
            seln.Status = SelectionStatus.Pending;
            seln.Price = null;

            mkt.Selections.Add(seln);

            fixture.Markets.Add(mkt);

            // STEP 3: invoke the delta rule
            MarketRulesManager manager = new MarketRulesManager(fixture.Id, stateprovider, rules);

            manager.ApplyRules(fixture); // this will not have any effect as we don't have any state yet

            manager.CommitChanges();

            manager.ApplyRules(fixture); // here is where the delta rule is invoked (note that we haven't changed anything on the fixture)

            manager.CommitChanges();

            // STEP 4: check the results (delta rule should have removed everything)
            fixture.Markets.Count.Should().Be(0);

            // STEP 5: change a single field
            seln.Price = 1.2;
            fixture.Markets.Add(mkt);
            mkt.Selections.Count().Should().Be(2);

            // STEP 6: apply the delta rule again
            manager.ApplyRules(fixture);

            // STEP 7: the market should not have been filtered out
            fixture.Markets.Count().Should().Be(1);
            fixture.Markets[0].Selections.Count().Should().Be(2);
        }