Exemplo n.º 1
0
        /// <summary>
        /// <para>
        /// Get SmoothScenario instances for sponsored spots. We try and return scenarios.
        /// </para>
        /// <para>
        /// Unfortunately we have some business rules regarding sponsor spots
        /// coded here. We should try and make it more data driven later on. The
        /// business rules are that the first sponsor spot is placed in break
        /// #1, the next in break #2.
        /// </para>
        /// </summary>
        private IReadOnlyCollection <SmoothScenario> GetSmoothScenariosForSponsoredSpots(
            IReadOnlyCollection <Spot> spotsForBreak,
            IReadOnlyList <SmoothBreak> progSmoothBreaks,
            IReadOnlyCollection <SmoothFailureMessagesForSpotsCollection> validateAddSpotsToBreakResults,
            int lastSmoothScenarioSequence,
            SpotPositionRules breakPositionRules,
            bool respectSpotTime)
        {
            if (progSmoothBreaks.Count == 0)
            {
                return(new List <SmoothScenario>());
            }

            var sponsoredSpots = spotsForBreak
                                 .Where(s => s.Sponsored);

            if (!sponsoredSpots.Any())
            {
                return(new List <SmoothScenario>());
            }

            var sponsoredSpot = sponsoredSpots.First();

            var validBreaksForSpotTime = progSmoothBreaks
                                         .Where(sb =>
            {
                var canAddSpotService = CanAddSpotService.Factory(sb);
                return(canAddSpotService.CanAddSpotWithTime(sponsoredSpot.StartDateTime, sponsoredSpot.EndDateTime));
            })
                                         .OrderBy(sb => sb.TheBreak.ScheduledDate);

            if (!validBreaksForSpotTime.Any())
            {
                return(new List <SmoothScenario>());
            }

            bool isRestrictedSpotTime = validBreaksForSpotTime.First().Position != 1 ||
                                        validBreaksForSpotTime.Last().Position != progSmoothBreaks[progSmoothBreaks.Count - 1].Position;

            var smoothScenarios = new List <SmoothScenario>();

            var listOfSpotValidations       = validateAddSpotsToBreakResults.ToList();
            var listOfProgrammeSmoothBreaks = progSmoothBreaks.ToList();

            // Check each break, see if there are sponsored spots that we could move
            foreach (var progSmoothBreak in progSmoothBreaks)
            {
                // Lists of groups of spots moved out of break, used for
                // preventing duplicate scenarios which is inefficient
                var externalSpotRefsMovedOutOfBreakByGroup = new HashSet <string>();

                // Get results for adding spot to break in its current state
                var validateAddSpotsToBreakResult = listOfSpotValidations[listOfProgrammeSmoothBreaks.IndexOf(progSmoothBreak)];

                // Check if any failures. Ignore if T1_BreakPosition which
                // happens if break requested and this break is not allowed If
                // break position not allowed then don't move any spots. This
                // would happen if a break request was specified and this isn't
                // the requested break
                if (validateAddSpotsToBreakResult[sponsoredSpot.Uid].Failures.Count > 0 &&    // Failures prevent spot being added
                    !validateAddSpotsToBreakResult[sponsoredSpot.Uid].Failures.Any(f => f.FailureMessage == SmoothFailureMessages.T1_BreakPosition))
                {
                    var spotGroupsToMove = new List <Spot[]>();

                    // Only consider moving spots from this break if any of the
                    // following conditions are true:
                    // - No break request and first or last break (as per
                    // business rules).
                    // - Requested break and this is requested break.
                    // - Spot has restricted times and break is within it.
                    bool addScenariosToFixFailures = false;

                    if (!HasBreakRequest(sponsoredSpot) &&
                        (
                            progSmoothBreak.Position == listOfProgrammeSmoothBreaks[0].Position ||
                            progSmoothBreak.Position == progSmoothBreaks[progSmoothBreaks.Count - 1].Position
                        )
                        )
                    {
                        addScenariosToFixFailures = true;
                    }
                    else if (HasBreakRequest(sponsoredSpot))
                    {
                        addScenariosToFixFailures = SpotUtilities.CanSpotBePlacedInRequestedBreakOrContainer(
                            sponsoredSpot,
                            progSmoothBreaks,
                            breakPositionRules,
                            respectSpotTime,
                            validBreaksForSpotTime,
                            isRestrictedSpotTime,
                            progSmoothBreak);
                    }
                    else if (SpotUtilities.IsBreakWithinSpotTimeRestriction(
                                 respectSpotTime,
                                 isRestrictedSpotTime,
                                 validBreaksForSpotTime,
                                 progSmoothBreak))
                    {
                        addScenariosToFixFailures = true;
                    }

                    if (addScenariosToFixFailures)
                    {
                        // See if we can find spots to move out of the break,
                        // check failures
                        foreach (var failure in validateAddSpotsToBreakResult[sponsoredSpot.Uid].Failures)
                        {
                            switch (failure.FailureMessage)
                            {
                            case SmoothFailureMessages.T1_CampaignClash:
                                MoveCampaignClashSpots(spotsForBreak, sponsoredSpot, progSmoothBreak, spotGroupsToMove);
                                break;

                            case SmoothFailureMessages.T1_InsufficentRemainingDuration:
                                MoveSpotsToIncreaseBreakAvailability(spotsForBreak, sponsoredSpot, progSmoothBreak, spotGroupsToMove);
                                break;

                            case SmoothFailureMessages.T1_ProductClash:
                                MoveProductClashSpots(spotsForBreak, sponsoredSpot, progSmoothBreak, spotGroupsToMove);
                                break;

                            case SmoothFailureMessages.T1_RequestedPositionInBreak:
                                MoveRequestedPositionInBreakSpots(spotsForBreak, sponsoredSpot, progSmoothBreak, spotGroupsToMove);
                                break;
                            }
                        }
                    }

                    // Add scenario to move group of spots, avoid duplicating
                    // scenarios for same spot
                    foreach (var spotGroupToMove in spotGroupsToMove)
                    {
                        string externalSpotRefsForGroup = SpotUtilities.GetListOfSpotExternalReferences(
                            ",",
                            spotGroupToMove.ToList());

                        if (!externalSpotRefsMovedOutOfBreakByGroup.Contains(externalSpotRefsForGroup))
                        {
                            const int PriorityBase2 = 1_000_000;

                            var smoothScenario = new SmoothScenario()
                            {
                                Id       = Guid.NewGuid(),
                                Sequence = lastSmoothScenarioSequence + 1,
                                Priority = PriorityBase2 + (100_000 - spotGroupToMove[0].Preemptlevel)
                            };

                            smoothScenario.Actions.Add(
                                new SmoothActionMoveSpotToUnplaced(
                                    sequence: 1,
                                    spotGroupToMove.Select(s => s.ExternalSpotRef)
                                    )
                                );

                            smoothScenarios.Add(smoothScenario);

                            lastSmoothScenarioSequence = smoothScenarios.Last().Sequence;

                            _ = externalSpotRefsMovedOutOfBreakByGroup.Add(externalSpotRefsForGroup);
                        }
                    }
                }
            }

            return(smoothScenarios);
Exemplo n.º 2
0
        public void LogBestBreakFactorMessage(
            SmoothPass smoothPass,
            SmoothPassDefaultIteration smoothPassIteration,
            BestBreakFactorGroup bestBreakFactorGroup,
            Break theBreak,
            IReadOnlyCollection <Spot> spots,
            decimal?bestBreakScore,
            string message)
        {
            if (!_isloggingEnabled || !_logBestBreakFactor)
            {
                return;
            }

            string file = _logFilenameFactory.FilenameFor(LogFilenameFactory.LogFileType.BestBreak);

            bool addHeaders = !File.Exists(file);
            int  attempts   = 0;

            do
            {
                attempts++;

                try
                {
                    using var writer = new StreamWriter(file, true);
                    if (addHeaders)
                    {
                        writer.WriteLine(string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}{0}{7}{0}{8}{0}{9}{0}{10}", Delimiter, "ProcessorDateTime", "PassSeq", "PassIterationSeq", "PlaceSpotsSeq", "GroupName", "GroupSeq", "ExternalBreakRef", "Spots", "BestBreakScore", "Message"));
                    }

                    writer.WriteLine(string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}{0}{7}{0}{8}{0}{9}{0}{10}", Delimiter, _processorDateTimeToString,
                                                   smoothPass == null ? "" : smoothPass.Sequence.ToString(),
                                                   smoothPassIteration == null ? "" : smoothPassIteration.Sequence.ToString(),
                                                   0,
                                                   bestBreakFactorGroup == null ? "" : bestBreakFactorGroup.Name,
                                                   bestBreakFactorGroup == null ? "" : bestBreakFactorGroup.Sequence.ToString(),
                                                   theBreak == null ? "" : theBreak.ExternalBreakRef,
                                                   spots == null || spots.Count == 0 ? "" : SpotUtilities.GetListOfSpotExternalReferences(",", spots),
                                                   bestBreakScore == null ? "" : bestBreakScore.Value.ToString("0.000000000000000000000000000000"),
                                                   message));

                    writer.Flush();
                    writer.Close();

                    return;
                }
                catch (Exception exception) when(IsExceptionForFileInUse(exception) && attempts < 10)
                {
                    Thread.Sleep(100);
                }
            } while (attempts != -1);
        }