Пример #1
0
        /// <summary>
        /// Maps (converts) the provided <see cref="odds_change"/> instance to the <see cref="IOddsChange{T}"/> instance
        /// </summary>
        /// <param name="message">A <see cref="odds_change"/> instance to be mapped (converted)</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}" /> specifying the languages to which the mapped message will be translated</param>
        /// <param name="rawMessage">The raw message</param>
        /// <returns>A <see cref="IOddsChange{T}"/> instance constructed from information in the provided <see cref="odds_change"/></returns>
        public IOddsChange <T> MapOddsChange <T>(odds_change message, IEnumerable <CultureInfo> cultures, byte[] rawMessage) where T : ISportEvent
        {
            Guard.Argument(message, nameof(message)).NotNull();

            var culturesList = cultures as List <CultureInfo> ?? cultures.ToList();

            var markets = message.odds?.market?.Select(m => GetMarketWithOdds(GetEventForNameProvider <T>(message.EventURN, message.SportId, culturesList), m, message.ProducerId, message.SportId, culturesList)).ToList();

            return(new OddsChange <T>(new MessageTimestamp(message.GeneratedAt, message.SentAt, message.ReceivedAt, SdkInfo.ToEpochTime(DateTime.Now)),
                                      _producerManager.Get(message.product),
                                      GetEventForMessage <T>(URN.Parse(message.event_id), message.SportId, culturesList),
                                      message.request_idSpecified
                    ? (long?)message.request_id
                    : null,
                                      MessageMapperHelper.GetEnumValue(message.odds_change_reasonSpecified, message.odds_change_reason, OddsChangeReason.NORMAL),
                                      message.odds != null && message.odds.betstop_reasonSpecified
                    ? (int?)message.odds.betstop_reason
                    : null,
                                      message.odds != null && message.odds.betting_statusSpecified
                    ? (int?)message.odds.betting_status
                    : null,
                                      markets,
                                      message.odds_generation_properties,
                                      _namedValuesProvider,
                                      rawMessage));
        }
Пример #2
0
        public IOddsChange <T> MapOddsChange <T>(odds_change message, IEnumerable <CultureInfo> cultures, byte[] rawMessage) where T : ISportEvent
        {
            Contract.Requires(message != null);
            Contract.Ensures(Contract.Result <IOddsChange <T> >() != null);

            return(Contract.Result <IOddsChange <T> >());
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="OddsChangeEventArgs{T}"/> class
        /// </summary>
        /// <param name="messageMapper">A <see cref="IFeedMessageMapper"/> used to map feed message to the one dispatched to the user</param>
        /// <param name="feedMessage">A <see cref="odds_change"/> message received from the feed</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the default languages to which the received message is translated</param>
        /// <param name="rawMessage">A raw message received from the feed</param>
        internal OddsChangeEventArgs(IFeedMessageMapper messageMapper, odds_change feedMessage, IEnumerable <CultureInfo> cultures, byte[] rawMessage)
        {
            Guard.Argument(messageMapper, nameof(messageMapper)).NotNull();
            Guard.Argument(feedMessage, nameof(feedMessage)).NotNull();
            Guard.Argument(cultures, nameof(cultures)).NotNull().NotEmpty();

            _messageMapper   = messageMapper;
            _feedMessage     = feedMessage;
            _defaultCultures = cultures as IReadOnlyCollection <CultureInfo>;
            _rawMessage      = rawMessage;
        }
        public void Init()
        {
            InitSportEventCache();
            _statusCache = new MemoryCache("eventsStatus");
            _processor   = new CacheMessageProcessor(_statusCache, new SportEventStatusMapperFactory(), _sportEventCache);

            var data = FileHelper.OpenFile(DirPath, InputXml);

            _record         = Deserializer.Deserialize <odds_change>(data);
            _record.SportId = URN.Parse("sr:sport:1000");
        }
Пример #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OddsChangeEventArgs{T}"/> class
        /// </summary>
        /// <param name="messageMapper">A <see cref="IFeedMessageMapper"/> used to map feed message to the one dispatched to the user</param>
        /// <param name="feedMessage">A <see cref="odds_change"/> message received from the feed</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the default languages to which the received message is translated</param>
        /// <param name="rawMessage">A raw message received from the feed</param>
        internal OddsChangeEventArgs(IFeedMessageMapper messageMapper, odds_change feedMessage, IEnumerable <CultureInfo> cultures, byte[] rawMessage)
        {
            Contract.Requires(messageMapper != null);
            Contract.Requires(feedMessage != null);
            Contract.Requires(cultures != null && cultures.Any());
            Contract.Ensures(_messageMapper != null);
            Contract.Ensures(_feedMessage != null);
            Contract.Ensures(_defaultCultures != null && _defaultCultures.Any());

            _messageMapper   = messageMapper;
            _feedMessage     = feedMessage;
            _defaultCultures = cultures as IReadOnlyCollection <CultureInfo>;
            _rawMessage      = rawMessage;
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OddsChangeEventArgs{T}"/> class
        /// </summary>
        /// <param name="messageMapper">A <see cref="IFeedMessageMapper"/> used to map feed message to the one dispatched to the user</param>
        /// <param name="feedMessage">A <see cref="odds_change"/> message received from the feed</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the default languages to which the received message is translated</param>
        /// <param name="rawMessage">A raw message received from the feed</param>
        internal OddsChangeEventArgs(IFeedMessageMapper messageMapper, odds_change feedMessage, IEnumerable <CultureInfo> cultures, byte[] rawMessage)
        {
            Guard.Argument(messageMapper, nameof(messageMapper)).NotNull();
            Guard.Argument(feedMessage, nameof(feedMessage)).NotNull();
            if (!cultures.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(cultures));
            }

            _messageMapper   = messageMapper;
            _feedMessage     = feedMessage;
            _defaultCultures = cultures as IReadOnlyCollection <CultureInfo>;
            _rawMessage      = rawMessage;

            _oddsChange = GetOddsChange();
        }
        private void TestEntityValues(IOddsChange <ICompetition> entity, odds_change record, AssertHelper assertHelper)
        {
            TestEventMessageProperties(assertHelper, entity, record.timestamp, record.product, record.event_id, record.RequestId);
            assertHelper.AreEqual(() => entity.ChangeReason,
                                  MessageMapperHelper.GetEnumValue <OddsChangeReason>(record.odds_change_reason));

            if (record.odds.betstop_reasonSpecified)
            {
                assertHelper.AreEqual(() => entity.BetStopReason.Id, record.odds.betstop_reason);
            }
            else
            {
                assertHelper.IsNull(() => entity.BetStopReason);
            }

            if (record.odds.betting_statusSpecified)
            {
                assertHelper.AreEqual(() => entity.BettingStatus.Id, record.odds.betting_status);
            }
            else
            {
                assertHelper.IsNull(() => entity.BettingStatus);
            }

            if (record.odds?.market == null || record.odds.market.Length == 0)
            {
                Assert.IsNull(entity.Markets);
            }
            else
            {
                foreach (var marketRecord in record.odds.market)
                {
                    var market = FindMarket(entity.Markets, marketRecord.id, marketRecord.specifiers);
                    Assert.IsNotNull(market, $"Market with id={marketRecord.id} does not exist on mapped message");
                    TestMarketValues(market, marketRecord);
                }
            }
        }
        /// <summary>
        /// Dispatches the <see cref="odds_change"/> message
        /// </summary>
        /// <param name="message">The <see cref="odds_change"/> message to dispatch</param>
        /// <param name="rawMessage">A raw message received from the feed</param>
        private void DispatchOddsChange(odds_change message, byte[] rawMessage)
        {
            var eventArgs = new OddsChangeEventArgs <T>(MessageMapper, message, DefaultCultures, rawMessage);

            Dispatch(OnOddsChange, eventArgs, message);
        }
Пример #9
0
        private void OddsChange(odds_change e, dbEntities cnn, string routeKey)
        {
            using (var dbContextTransaction = cnn.Database.BeginTransaction())
            {
                var spParams    = string.Empty;
                var sectionName = string.Empty;
                try
                {
                    var eventId      = e.event_id.Split(':').Last();
                    var product      = e.product;
                    var generatedAt  = e.timestamp;
                    var clockStopped = 0;

                    if (e.odds?.market != null)
                    {
                        sectionName = "odds_change";
                        var marketIdList      = string.Empty;
                        var specifierList     = string.Empty;
                        var statusList        = string.Empty;
                        var favoriteList      = string.Empty;
                        var outcomeIdList     = string.Empty;
                        var outcomeStatusList = string.Empty;
                        var outcomeOddList    = string.Empty;

                        foreach (var market in e.odds.market)
                        {
                            var marketId     = market.id;
                            var specifier    = market.specifiers?.Split('=').LastOrDefault()?.Trim();
                            var marketStatus = market.status;


                            if (market.outcome != null)
                            {
                                foreach (var outcome in market.outcome)
                                {
                                    sectionName        = "odds_change.market.outcome";
                                    marketIdList      += marketId + ",";
                                    specifierList     += specifier + ",";
                                    statusList        += marketStatus + ",";
                                    favoriteList      += market.favourite + ",";
                                    outcomeIdList     += outcome.id.Split(':').LastOrDefault() + ",";
                                    outcomeStatusList += outcome.active + ",";
                                    outcomeOddList    += outcome.odds.ToString(_nfi) + ",";
                                    marketId           = 0;
                                    if (!string.IsNullOrEmpty(specifier))
                                    {
                                        specifier = "*";
                                    }
                                }
                            }
                            else
                            {
                                marketIdList      += market.id + ",";
                                specifierList     += specifier + ",";
                                statusList        += market.status + ",";
                                favoriteList      += market.favourite + ",";
                                outcomeIdList     += string.Empty + ",";
                                outcomeStatusList += string.Empty + ",";
                                outcomeOddList    += string.Empty + ",";
                            }
                        }

                        sectionName = "execute BETDATA_ODDSCHANGE";
                        spParams    = "EXECUTE PROCEDURE BETDATA_ODDSCHANGE_MULTI(";
                        spParams   += SourceId + ",";
                        spParams   += eventId + ",";
                        spParams   += "'" + marketIdList.Substring(0).Trim() + "',";
                        spParams   += "'" + specifierList.Substring(0).Trim() + "',";
                        spParams   += "'" + statusList.Substring(0).Trim() + "',";
                        spParams   += "'" + favoriteList.Substring(0).Trim() + "',";
                        spParams   += "'" + outcomeIdList.Substring(0).Trim() + "',";
                        spParams   += "'" + outcomeStatusList.Substring(0).Trim() + "',";
                        spParams   += "'" + outcomeOddList.Substring(0).Trim() + "',";
                        spParams   += generatedAt + ")";
                        cnn.Database.ExecuteSqlCommand(spParams.Trim());
                    }


                    if (e.sport_event_status != null)
                    {
                        sectionName = "odds_change.sport_event_status";
                        var periodNumberList          = string.Empty;
                        var periodHomeScoreList       = string.Empty;
                        var periodAwayScoreList       = string.Empty;
                        var periodMatchStatusCodeList = string.Empty;
                        if (e.sport_event_status?.period_scores != null)
                        {
                            if (e.sport_event_status.period_scores.Length > 0)
                            {
                                sectionName = "odds_change.sport_event_status.period_scores";

                                periodNumberList = e.sport_event_status.period_scores
                                                   .Aggregate(string.Empty, (current, s) => current + "," + s.number).Substring(1)
                                                   .Trim();
                                periodHomeScoreList = e.sport_event_status.period_scores
                                                      .Aggregate(string.Empty, (current, s) => current + "," + s.home_score).Substring(1)
                                                      .Trim();
                                periodAwayScoreList = e.sport_event_status.period_scores
                                                      .Aggregate(string.Empty, (current, s) => current + "," + s.away_score).Substring(1)
                                                      .Trim();
                                periodMatchStatusCodeList = e.sport_event_status.period_scores
                                                            .Aggregate(string.Empty, (current, s) => current + "," + s.match_status_code)
                                                            .Substring(1).Trim();

                                periodNumberList          += ",";
                                periodHomeScoreList       += ",";
                                periodAwayScoreList       += ",";
                                periodMatchStatusCodeList += ",";
                            }
                        }

                        if (e.sport_event_status?.clock?.stopped != null)
                        {
                            clockStopped = e.sport_event_status.clock.stopped ? 1 : 0;
                        }


                        sectionName = "execute BET_EVENTDETAILS_UI";
                        spParams    = "EXECUTE PROCEDURE BET_EVENTDETAILS_UI(";
                        spParams   += SourceId + ",";
                        spParams   += eventId + ",";
                        spParams   += product + ",";
                        spParams   += "'" + e.sport_event_status?.clock?.match_time + "',";
                        spParams   += "'" + e.sport_event_status?.clock?.stoppage_time + "',";
                        spParams   += "'" + e.sport_event_status?.clock?.stoppage_time_announced + "',";
                        spParams   += "'" + e.sport_event_status?.clock?.remaining_time + "',";
                        spParams   += "'" + e.sport_event_status?.clock?.remaining_time_in_period + "',";
                        spParams   += clockStopped + ",";
                        spParams   += (e.sport_event_status?.statistics?.corners.home ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.corners.away ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.red_cards.home ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.red_cards.away ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.yellow_cards.home ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.yellow_cards.away ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.yellow_red_cards.home ?? 0) + ",";
                        spParams   += (e.sport_event_status?.statistics?.yellow_red_cards.away ?? 0) + ",";
                        spParams   += e.sport_event_status?.status + ",";
                        spParams   += e.sport_event_status?.home_score.ToString(_nfi) + ",";
                        spParams   += e.sport_event_status?.away_score.ToString(_nfi) + ",";
                        spParams   += e.sport_event_status?.match_status + ",";
                        spParams   += (e.odds?.betstop_reason ?? 0) + ",";
                        spParams   += (e.odds?.betting_status ?? 0) + ",";
                        spParams   += "'" + periodNumberList.Substring(0).Trim() + "',";
                        spParams   += "'" + periodHomeScoreList.Substring(0).Trim() + "',";
                        spParams   += "'" + periodAwayScoreList.Substring(0).Trim() + "',";
                        spParams   += "'" + periodMatchStatusCodeList.Substring(0).Trim() + "',";
                        spParams   += generatedAt + ")";
                        cnn.Database.ExecuteSqlCommand(spParams.Trim());
                    }

                    dbContextTransaction.Commit();
                    SerilogHelper.Information($"{routeKey} {UtcHelper.GetDifferenceFromTimestamp(e.timestamp) + "ms"}");
                }
                catch (Exception ex)
                {
                    dbContextTransaction.Rollback();
                    SerilogHelper.Exception(
                        $"Unknown exception in {routeKey} SectionName:{sectionName} SQL:{spParams.Trim()}", ex);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Validates the provided <see cref="odds_change" /> message
        /// </summary>
        /// <param name="message">The <see cref="odds_change" /> message to validate</param>
        /// <returns>The <see cref="ValidationResult" /> specifying the result of validation</returns>
        protected ValidationResult ValidateOddsChange(odds_change message)
        {
            Contract.Requires(message != null);

            ValidateMessageProducer(message);

            if (!ValidateMessage(message))
            {
                return(ValidationResult.FAILURE);
            }

            var result = ValidationResult.SUCCESS;

            if (message.odds_change_reasonSpecified && !MessageMapperHelper.IsEnumMember <OddsChangeReason>(message.odds_change_reason))
            {
                LogWarning(message, "odds_change_reason", message.odds_change_reason);
                result = ValidationResult.PROBLEMS_DETECTED;
            }

            if (message.odds == null)
            {
                return(result);
            }

            if (message.odds.betstop_reasonSpecified && !_namedValuesProvider.BetStopReasons.IsValueDefined(message.odds.betstop_reason))
            {
                LogWarning(message, "betstop_reason", message.odds.betstop_reason);
                result = ValidationResult.PROBLEMS_DETECTED;
            }
            if (message.odds.betting_statusSpecified && !_namedValuesProvider.BettingStatuses.IsValueDefined(message.odds.betting_status))
            {
                LogWarning(message, "betting_status", message.odds.betting_status);
                result = ValidationResult.PROBLEMS_DETECTED;
            }

            if (message.odds.market == null || !message.odds.market.Any())
            {
                return(result);
            }

            for (var marketIndex = 0; marketIndex < message.odds.market.Length; marketIndex++)
            {
                var market = message.odds.market[marketIndex];
                if (market.statusSpecified && !MessageMapperHelper.IsEnumMember <MarketStatus>(market.status))
                {
                    LogFailure(message, $"market[{marketIndex}].market_status", market.status);
                    return(ValidationResult.FAILURE);
                }

                //if (market.favouriteSpecified && market.favourite != 1)
                //{
                //    LogWarning(message, $"market[{marketIndex}].favourite", market.favourite);
                //    result = ValidationResult.PROBLEMS_DETECTED;
                //}

                if (!ValidateSpecifiers(message, market, marketIndex))
                {
                    result = ValidationResult.PROBLEMS_DETECTED;
                }

                if (!CheckSpecifiersAsync(message.ProducerId, market.id, market.Specifiers).Result)
                {
                    result = ValidationResult.PROBLEMS_DETECTED;
                }

                if (market.outcome == null || !market.outcome.Any())
                {
                    continue;
                }

                for (var outcomeIndex = 0; outcomeIndex < market.outcome.Length; outcomeIndex++)
                {
                    var outcome = market.outcome[outcomeIndex];
                    result = ValidateOddsChangeOutcomes(message, market, outcome, result);
                }
            }
            return(result);
        }
        /// <summary>
        /// Validates the provided <see cref="odds_change" /> message
        /// </summary>
        /// <param name="message">The <see cref="odds_change" /> message to validate</param>
        /// <returns>The <see cref="ValidationResult" /> specifying the result of validation</returns>
        protected ValidationResult ValidateOddsChange(odds_change message)
        {
            Guard.Argument(message, nameof(message)).NotNull();

            ValidateMessageProducer(message);

            if (!ValidateMessage(message))
            {
                return(ValidationResult.FAILURE);
            }

            var result = ValidationResult.SUCCESS;

            if (message.odds_change_reasonSpecified && !MessageMapperHelper.IsEnumMember <OddsChangeReason>(message.odds_change_reason))
            {
                LogWarning(message, "odds_change_reason", message.odds_change_reason);
                result = ValidationResult.PROBLEMS_DETECTED;
            }

            if (message.odds == null)
            {
                return(result);
            }

            if (message.odds.betstop_reasonSpecified && !_namedValuesProvider.BetStopReasons.IsValueDefined(message.odds.betstop_reason))
            {
                LogWarning(message, "betstop_reason", message.odds.betstop_reason);
                result = ValidationResult.PROBLEMS_DETECTED;
            }
            if (message.odds.betting_statusSpecified && !_namedValuesProvider.BettingStatuses.IsValueDefined(message.odds.betting_status))
            {
                LogWarning(message, "betting_status", message.odds.betting_status);
                result = ValidationResult.PROBLEMS_DETECTED;
            }

            if (message.odds.market == null || !message.odds.market.Any())
            {
                return(result);
            }

            foreach (var market in message.odds.market)
            {
                if (market.statusSpecified && !MessageMapperHelper.IsEnumMember <MarketStatus>(market.status))
                {
                    LogFailure(message, $"market {market.id} market_status", market.status);
                    return(ValidationResult.FAILURE);
                }

                if (!ValidateSpecifiers(message, market, market.id))
                {
                    result = ValidationResult.PROBLEMS_DETECTED;
                }

                if (!CheckSpecifiersAsync(message.ProducerId, market.id, market.Specifiers).Result)
                {
                    result = ValidationResult.PROBLEMS_DETECTED;
                }

                if (market.outcome == null || !market.outcome.Any())
                {
                    continue;
                }

                foreach (var outcome in market.outcome)
                {
                    result = ValidateOddsChangeOutcomes(message, market, outcome, result);
                }
            }
            return(result);
        }