/// <summary>
        /// Attempt to place unplaced spots by moving other spots. These are
        /// spots that couldn't be placed during the main pass, should only be
        /// spots that couldn't be placed due to no break with sufficient
        /// remaining time.
        /// </summary>
        public SmoothPassResult Execute(
            SmoothPassUnplaced smoothPass,
            IReadOnlyCollection <Break> breaksBeingSmoothed,
            ISet <Guid> spotIdsUsed,
            IReadOnlyCollection <Spot> spots,
            IReadOnlyDictionary <Guid, SpotInfo> spotInfos)
        {
            var smoothPassResult = new SmoothPassResult(smoothPass.Sequence);

            if (MaximumOfTwoBreaksWithRemainingTime(_smoothProgramme.ProgrammeSmoothBreaks))
            {
                return(smoothPassResult);
            }

            // Get all spots for pass, order by priority for processing
            var spotFilter = new SpotFilter()
            {
                Sponsored                        = null,
                Preemptable                      = null,
                MinPreemptLevel                  = null, // Any
                MaxPreemptLevel                  = null, // Any
                HasBreakRequest                  = null, // Any
                BreakRequests                    = null,
                HasPositionInBreakRequest        = null, // Any
                PositionInBreakRequestsToExclude = null, // Any
                HasMultipartSpots                = null,
                MultipartSpots                   = null, // Any
                HasProductClashCode              = null,
                ProductClashCodesToExclude       = null,
                ExternalCampaignRefsToExclude    = _smoothConfiguration.ExternalCampaignRefsToExclude,
                HasSpotEndTime                   = null,
                MinSpotLength                    = null,
                MaxSpotLength                    = null,
                SpotIdsToExclude                 = spotIdsUsed
            };

            // Order the spots by priority
            var spotsToPlace = GetSpots(spotFilter, spots, spotInfos);
            var spotsOrdered = _smoothConfiguration.SortSpotsToPlace(
                spotsToPlace,
                (_smoothProgramme.Programme.StartDateTime, _smoothProgramme.Programme.Duration)
                );

            // Try and place spots
            foreach (var spot in spotsOrdered)
            {
                try
                {
                    PlaceSpotsResult placeSpotsResult = PlaceSpot(
                        smoothPass,
                        spot,
                        spotInfos,
                        _smoothProgramme.ProgrammeSmoothBreaks,
                        breaksBeingSmoothed,
                        spotIdsUsed);

                    smoothPassResult.PlaceSpotsResultList.Add(placeSpotsResult);
                }
                catch (Exception exception)
                {
                    RaiseException($"Error trying to place unplaced spot {spot.ExternalSpotRef}", exception);
                }
            }

            return(smoothPassResult);
Esempio n. 2
0
        /// <summary>
        /// Gets spots matching filter criteria
        /// </summary>
        /// <param name="spotFilter"></param>
        /// <param name="spots"></param>
        /// <param name="spotInfos"></param>
        /// <returns></returns>
        protected IEnumerable <Spot> GetSpots(
            SpotFilter spotFilter,
            IReadOnlyCollection <Spot> spots,
            IReadOnlyDictionary <Guid, SpotInfo> spotInfos)
        {
            var spotsOutput = new List <Spot>(spots);

            // Remove specific spots to exclude
            _ = spotsOutput.RemoveAll(s => !s.ClientPicked);

            if (spotFilter.SpotIdsToExclude?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s => spotFilter.SpotIdsToExclude.Contains(s.Uid));
            }

            // Remove spots that don't meet criteria
            if (spotFilter.MinPreemptLevel != null)
            {
                _ = spotsOutput.RemoveAll(s => s.Preemptlevel < spotFilter.MinPreemptLevel);
            }

            if (spotFilter.MaxPreemptLevel != null)
            {
                _ = spotsOutput.RemoveAll(s => s.Preemptlevel > spotFilter.MaxPreemptLevel);
            }

            if (spotFilter.Sponsored != null)
            {
                _ = spotsOutput.RemoveAll(s => s.Sponsored != spotFilter.Sponsored);
            }

            if (spotFilter.Preemptable != null)
            {
                _ = spotsOutput.RemoveAll(s => s.Preemptable != spotFilter.Preemptable);
            }

            if (spotFilter.HasBreakRequest != null)
            {
                _ = spotsOutput.RemoveAll(s =>
                                          (spotFilter.HasBreakRequest == true && String.IsNullOrEmpty(s.BreakRequest)) ||
                                          (spotFilter.HasBreakRequest == false && !String.IsNullOrEmpty(s.BreakRequest))
                                          );
            }

            if (spotFilter.BreakRequests?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s =>
                                          (!String.IsNullOrEmpty(s.BreakRequest) && !spotFilter.BreakRequests.Contains(s.BreakRequest)) ||
                                          (String.IsNullOrEmpty(s.BreakRequest) && !spotFilter.BreakRequests.Contains(null))
                                          );
            }

            if (spotFilter.HasPositionInBreakRequest != null)
            {
                _ = spotsOutput.RemoveAll(s =>
                                          (spotFilter.HasPositionInBreakRequest == true && String.IsNullOrEmpty(s.RequestedPositioninBreak)) ||
                                          (spotFilter.HasPositionInBreakRequest == false && !String.IsNullOrEmpty(s.RequestedPositioninBreak))
                                          );
            }

            if (spotFilter.PositionInBreakRequestsToExclude?.Any() == true)
            {
                _ = spotsOutput.RemoveAll(s => spotFilter.PositionInBreakRequestsToExclude.Contains(s.RequestedPositioninBreak));
            }

            if (spotFilter.HasMultipartSpots != null)
            {
                _ = spotsOutput.RemoveAll(s =>
                                          (spotFilter.HasMultipartSpots == true && !s.IsMultipartSpot) ||
                                          (spotFilter.HasMultipartSpots == false && s.IsMultipartSpot)
                                          );
            }

            if (spotFilter.MultipartSpots?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s => s.IsMultipartSpot && !spotFilter.MultipartSpots.Contains(s.MultipartSpot));
            }

            if (spotFilter.ExternalCampaignRefsToExclude?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s => spotFilter.ExternalCampaignRefsToExclude.Contains(s.ExternalCampaignNumber));
            }

            if (spotFilter.ProductClashCodesToExclude?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s => spotFilter.ProductClashCodesToExclude.Contains(spotInfos[s.Uid].ProductClashCode));
            }

            if (spotFilter.HasProductClashCode != null)
            {
                var spotsToRemove = new List <Spot>();

                foreach (var spot in spotsOutput)
                {
                    SpotInfo spotInfo = spotInfos[spot.Uid];

                    if ((spotFilter.HasProductClashCode == true && String.IsNullOrEmpty(spotInfo.ProductClashCode)) ||
                        (spotFilter.HasProductClashCode == false && !String.IsNullOrEmpty(spotInfo.ProductClashCode))
                        )
                    {
                        spotsToRemove.Add(spot);
                    }
                }

                if (spotsToRemove.Count > 0)
                {
                    _ = spotsOutput.RemoveAll(s => spotsToRemove.Contains(s));
                }
            }

            if (spotFilter.MinSpotLength != null)
            {
                _ = spotsOutput.RemoveAll(s => s.SpotLength.ToTimeSpan() < spotFilter.MinSpotLength);
            }

            if (spotFilter.MaxSpotLength != null)
            {
                _ = spotsOutput.RemoveAll(s => s.SpotLength.ToTimeSpan() > spotFilter.MaxSpotLength);
            }

            if (spotFilter.ProductAdvertiserIdentifiersToExclude?.Count > 0)
            {
                _ = spotsOutput.RemoveAll(s =>
                                          spotFilter.ProductAdvertiserIdentifiersToExclude.Contains(spotInfos[s.Uid].ProductAdvertiserIdentifier)
                                          );
            }

            if (spotFilter.HasSpotEndTime != null)
            {
                if (spotFilter.HasSpotEndTime.Value)
                {
                    _ = spotsOutput.RemoveAll(s => s.EndDateTime < s.StartDateTime);
                }
                else
                {
                    _ = spotsOutput.RemoveAll(s => s.EndDateTime > s.StartDateTime);
                }
            }

            // Order will be set elsewhere
            return(spotsOutput);
        }