private void SetupTestData( out IReadOnlyCollection<Break> breaksBeingSmoothed, out SmoothBreak theSmoothBreak, out IReadOnlyCollection<Programme> scheduleProgrammes, out List<Spot> spotsForBreak, out SalesArea salesArea, out IReadOnlyDictionary<string, Clash> clashesByExternalRef, out IReadOnlyDictionary<Guid, SpotInfo> spotInfos, out ProductClashRules productClashRule, out SmoothResources smoothResources, out IClashExposureCountService clashExposureCountService, out SponsorshipRestrictionService sponsorshipRestrictionsService) { breaksBeingSmoothed = _repositoryWrapper.LoadAllTestBreaks().ToList(); theSmoothBreak = new SmoothBreak(breaksBeingSmoothed.First(), 1); scheduleProgrammes = _repositoryWrapper.LoadAllProgrammes().ToList(); spotsForBreak = new List<Spot>() { _spot }; salesArea = _repositoryWrapper.LoadAllSalesArea().First(); clashesByExternalRef = _repositoryWrapper.LoadAllClashes().ToDictionary(c => c.Externalref); spotInfos = SpotInfo.Factory( spotsForBreak, _repositoryWrapper.LoadAllProducts().ToDictionary(p => p.Externalidentifier), clashesByExternalRef ); productClashRule = ProductClashRules.LimitOnExposureCount; smoothResources = new SmoothResources(); clashExposureCountService = ClashExposureCountService.Create(); sponsorshipRestrictionsService = SponsorshipRestrictionService.Factory( spotInfos, new SponsorshipRestrictionFilterService(ImmutableList.Create<Sponsorship>()), new SmoothSponsorshipTimelineManager(new List<SmoothSponsorshipTimeline>()), scheduleProgrammes.First(), DebugLogger); }
HasClashExceptionIncludesAndExcludes( SmoothBreak theSmoothBreak, bool respectClashExceptions, SmoothResources smoothResources, SmoothFailureMessagesForSpotsCollection result, Spot spot, Guid spotUid) { (bool spotHasClashExceptionIncludes, bool spotHasClashExceptionExcludes)clashExceptionResults = (false, false); if (!respectClashExceptions) { return(clashExceptionResults); } var checkClashExceptionsResults = smoothResources .ClashExceptionChecker.CheckClashExceptions(theSmoothBreak, spot); clashExceptionResults.spotHasClashExceptionIncludes = checkClashExceptionsResults .Any(cer => cer.ClashException.IncludeOrExclude == IncludeOrExclude.I); clashExceptionResults.spotHasClashExceptionExcludes = checkClashExceptionsResults .Any(cer => cer.ClashException.IncludeOrExclude == IncludeOrExclude.E); if (clashExceptionResults.spotHasClashExceptionIncludes) { result.Add(spotUid, SmoothFailureMessages.T1_ProductClash); } return(clashExceptionResults); }
public SpotDurationBalanceBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak) { _spots = spots; _smoothBreak = smoothBreak; }
public IsLastBreakBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <SmoothBreak> progSmoothBreaks) { _smoothBreak = smoothBreak; _progSmoothBreaks = progSmoothBreaks; }
/// <summary> /// Determines whether this Spot instance can be placed within the requested /// break or container. /// </summary> /// <param name="spot">The spot.</param> /// <param name="progSmoothBreaks">The prog smooth breaks.</param> /// <param name="breakPositionRules">The break position rules.</param> /// <param name="respectSpotTime">if set to <c>true</c>, respect spot time.</param> /// <param name="validBreaksForSpotTime">The valid breaks for spot time.</param> /// <param name="isRestrictedSpotTime">if set to <c>true</c>, is restricted spot time.</param> /// <param name="progSmoothBreak">The prog smooth break.</param> /// <returns> /// <c>true</c> if this Spot instance can be placed within the break or container requested; otherwise, <c>false</c>. /// </returns> public static bool CanSpotBePlacedInRequestedBreakOrContainer( Spot spot, IReadOnlyList <SmoothBreak> progSmoothBreaks, SpotPositionRules breakPositionRules, bool respectSpotTime, IOrderedEnumerable <SmoothBreak> validBreaksForSpotTime, bool isRestrictedSpotTime, SmoothBreak progSmoothBreak) { var canAddSpotService = CanAddSpotService.Factory(progSmoothBreak); string spotBreakOrContainerRequest = spot.BreakRequest; if (ContainerReference.TryParse(spotBreakOrContainerRequest, out ContainerReference cr)) { spotBreakOrContainerRequest = cr.ToString(); } if (canAddSpotService.CanAddSpotWithBreakRequest(spotBreakOrContainerRequest, progSmoothBreaks, breakPositionRules)) { return(true); } else if (IsBreakWithinSpotTimeRestriction(respectSpotTime, isRestrictedSpotTime, validBreaksForSpotTime, progSmoothBreak)) { return(true); } return(false); }
public RandomBreakBreakFactor( IReadOnlyCollection <double> randomScoreByBreak, SmoothBreak smoothBreak) { _randomScoreByBreak = randomScoreByBreak; _smoothBreak = smoothBreak; }
public IsLeavesDefaultBreakMultipleDurationsOrFillsBreakBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak) { _spots = spots; _smoothBreak = smoothBreak; }
public IsFillsBreakDurationBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <Spot> spots) { _smoothBreak = smoothBreak; _spots = spots; }
private static void ValidateWithSpotRestrictions( SmoothBreak theSmoothBreak, Programme programme, SalesArea salesArea, IReadOnlyCollection <Spot> spotsForBreak, SmoothResources smoothResources, IReadOnlyCollection <Break> breaksBeingSmoothed, IReadOnlyCollection <Programme> scheduleProgrammes, SmoothFailureMessagesForSpotsCollection result) { var anyRestrictions = CheckRestrictionsForSpots( spotsForBreak, theSmoothBreak.TheBreak, programme, salesArea, smoothResources, breaksBeingSmoothed, scheduleProgrammes); foreach (var item in anyRestrictions) { foreach (var failure in item.Value.Failures) { result.Add(item.Key, failure.FailureMessage, failure.Restriction); } } }
public IsFirstHalfOfProgrammeBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <SmoothBreak> progSmoothBreaks) { _smoothBreak = smoothBreak; _progSmoothBreaks = progSmoothBreaks; }
public IsLeaves15SecBreakMultipleDurationsBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak) { _spots = spots; _smoothBreak = smoothBreak; }
public BreaksInAscendingPositionBreakFactor( IReadOnlyCollection <SmoothBreak> progSmoothBreaks, SmoothBreak smoothBreak) { _progSmoothBreaks = progSmoothBreaks; _smoothBreak = smoothBreak; }
public FewestRequestedPositionInBreakRequestsFirstOrLastOnlyBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <Spot> spots) { _smoothBreak = smoothBreak; _spots = spots; }
/// <summary>Unplaces the restricted spot.</summary> /// <param name="smoothPass">The smooth pass.</param> /// <param name="smoothSpot">The smooth spot.</param> /// <param name="smoothBreak">The smooth break.</param> /// <param name="spotActionMessage">The spot action message.</param> /// <param name="spotIdsUsed">The spot ids used.</param> private void UnplaceRestrictedSpot( SmoothPass smoothPass, SmoothSpot smoothSpot, SmoothBreak smoothBreak, string spotActionMessage, ISet <Guid> spotIdsUsed) { RaiseInfo( $"Unplacing booked spot {smoothSpot.Spot.ExternalSpotRef} " + $"from break {smoothBreak.TheBreak.ExternalBreakRef}: {spotActionMessage}" ); SpotPlacementService.RemoveSpotFromBreak( smoothBreak, smoothSpot.Spot, spotIdsUsed, _sponsorshipRestrictionService ); smoothSpot.IsCurrent = true; _smoothDiagnostics.LogSpotAction( smoothPass, 0, smoothSpot.Spot, smoothBreak, SmoothSpot.SmoothSpotActions.RemoveSpotFromBreak, spotActionMessage); }
public IsNoSponsorSpotsForSameSponsorBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <Spot> spots, IReadOnlyDictionary <Guid, SpotInfo> spotInfos) { _smoothBreak = smoothBreak; _spots = spots; _spotInfos = spotInfos; }
public FewestMatchingSponsorSpotsBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak, IReadOnlyDictionary <Guid, SpotInfo> spotInfos) { _spots = spots; _smoothBreak = smoothBreak; _spotInfos = spotInfos; }
public FewestCampaignClashesBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak, ICampaignClashChecker campaignClashChecker) { _spots = spots; _smoothBreak = smoothBreak; _campaignClashChecker = campaignClashChecker; }
/// <summary> /// <para> Adds spots to break. If multiple spots are being /// added then they're typically related. E.g. TOP & TAIL. /// </para> /// <para> The break sequence will be updated later when the break has /// been filled, will be updated to start from 1. For specific positions /// (FIB, SIB etc) then the break sequence is assigned as a large positive /// or negative number and everything else is inserted between. /// </para> /// </summary> public static List <SmoothSpot> AddSpotsToBreak( SmoothBreak smoothBreak, int smoothPassSequence, int smoothPassIterationSequence, IReadOnlyCollection <Spot> spots, SpotPositionRules passRequestedPositionInBreakRules, bool canMoveSpotToOtherBreak, ICollection <Guid> spotIdsUsed, string bestBreakFactorGroupName, IReadOnlyDictionary <Guid, SpotInfo> spotInfos, SponsorshipRestrictionService sponsorshipRestrictionService ) { var smoothSpots = new List <SmoothSpot>(); foreach (Spot spot in spots) { IReadOnlyDictionary <string, bool> hasSpotPositions = smoothBreak.GetSpotPositions(); int breakSeq = SpotPositioning.GetBreakSequenceNumber( smoothBreak, passRequestedPositionInBreakRules, spot, hasSpotPositions ); // Default break sequence to middle of break if (breakSeq == 0) { breakSeq = SpotPositioning.GetBreakSeqForMiddleOfBreak(smoothBreak); } smoothSpots.Add( smoothBreak.AddSpot( spot, smoothPassSequence, smoothPassIterationSequence, breakSeq, currentSpot: true, canMoveSpotToOtherBreak, bestBreakFactorGroupName, spotInfos[spot.Uid].ExternalBreakRefAtRunStart ) ); sponsorshipRestrictionService.TriggerRecalculationOfAllowedRestrictionLimits( SpotAction.AddSpot, spot, smoothBreak.TheBreak ); FlagSpotAsUsed(spot, spotIdsUsed); } return(smoothSpots); }
public FewestProductClashesAtChildLevelBreakFactor( IReadOnlyCollection <Spot> spots, SmoothBreak smoothBreak, IReadOnlyDictionary <Guid, SpotInfo> spotInfos, IProductClashChecker productClashChecker) { _spots = spots; _smoothBreak = smoothBreak; _spotInfos = spotInfos; _productClashChecker = productClashChecker; }
internal static bool IsBreakWithinSpotTimeRestriction( bool respectSpotTime, bool isRestrictedSpotTime, IOrderedEnumerable <SmoothBreak> validBreaksForSpotTime, SmoothBreak progSmoothBreak) { return(isRestrictedSpotTime && respectSpotTime && progSmoothBreak.Position >= validBreaksForSpotTime.First().Position && progSmoothBreak.Position <= validBreaksForSpotTime.LastOrDefault()?.Position); }
public IsOtherBreaksHaveSpotsForSameSponsorBreakFactor( SmoothBreak smoothBreak, List <Spot> sponsoredSpots, IReadOnlyCollection <SmoothBreak> progSmoothBreaks, IReadOnlyDictionary <Guid, SpotInfo> spotInfos) { _smoothBreak = smoothBreak; _sponsoredSpots = sponsoredSpots; _progSmoothBreaks = progSmoothBreaks; _spotInfos = spotInfos; }
public void AddingSpotToBreakFlagsSpotAsUsed() { // Arrange var smoothBreak = new SmoothBreak( Fixture.Create <Break>(), position: 1); var spot = Fixture.Build <Spot>() .Without(p => p.MultipartSpot) .Create(); var spots = new List <Spot> { spot }; var spotInfos = new Dictionary <Guid, SpotInfo> { [spot.Uid] = Fixture.Create <SpotInfo>() }; var spotIdsUsed = new HashSet <Guid>(); var mockSponsorshipRestrictionService = new Mock <SponsorshipRestrictionService>( new Mock <IReadOnlyList <SponsorshipRestrictionFilterResults> >().Object, new Mock <ISmoothSponsorshipTimelineManager>().Object, new Mock <IReadOnlyDictionary <Guid, SpotInfo> >().Object, new Mock <Action <string, Exception> >().Object ); mockSponsorshipRestrictionService.Setup(s => s.TriggerRecalculationOfAllowedRestrictionLimits( It.IsAny <SpotAction>(), It.IsAny <Spot>(), It.IsAny <Break>())) .Verifiable(); // Act _ = Act(() => { return(SpotPlacementService.AddBookedSpotsToBreak( smoothBreak, spots, spotInfos, spotIdsUsed, mockSponsorshipRestrictionService.Object )); }); // Assert _ = spotIdsUsed.Should().Contain(spot.Uid, becauseArgs: null); }
CanAddSpotWithBreakType_SpotBreakTypeMismatchBreakBreakType_SpotCannotBeAddedToTheBreak() { // Arrange Break fakeBreak = BreakWithValidBreakTypeFactory(); var fakeSmoothBreak = new SmoothBreak(fakeBreak, 1); var service = CanAddSpotService.Factory(fakeSmoothBreak); // Act var result = service.CanAddSpotWithBreakType("DF-DIFFERENT BREAK TYPE"); // Assert _ = result.Should().BeFalse(because: null); }
CanAddSpotWithBreakType_SpotBreakTypeMatchesBreaksBreakType_SpotCanBeAddedToTheBreak() { // Arrange Break fakeBreak = BreakWithValidBreakTypeFactory(); var fakeSmoothBreak = new SmoothBreak(fakeBreak, 1); var service = CanAddSpotService.Factory(fakeSmoothBreak); // Act var result = service.CanAddSpotWithBreakType(ValidBreakType); // Assert _ = result.Should().BeTrue(because: null); }
SpotCountAndAverageLength(SmoothBreak smoothBreak) { var spots = smoothBreak.SmoothSpots .Select(s => s.Spot) .ToList(); int spotsCount = spots.Count; TimeSpan avgSpotLength = spotsCount > 0 ? SpotUtilities.GetAverageSpotLength(spots) : TimeSpan.Zero; int averageSpotLengthInSeconds = (int)avgSpotLength.TotalSeconds; return(spotsCount, averageSpotLengthInSeconds); }
public FewestProductClashesBreakFactor( SmoothBreak smoothBreak, IReadOnlyCollection <Spot> spots, IReadOnlyDictionary <Guid, SpotInfo> spotInfos, IReadOnlyDictionary <string, Product> productsByExternalRef, IReadOnlyDictionary <string, Clash> clashesByExternalRef, IProductClashChecker productClashChecker, IClashExposureCountService effectiveClashExposureCount) { _smoothBreak = smoothBreak; _spots = spots; _spotInfos = spotInfos; _productsByExternalRef = productsByExternalRef; _clashesByExternalRef = clashesByExternalRef; _productClashChecker = productClashChecker; _effectiveClashExposureCount = effectiveClashExposureCount; }
public void IsSpotEligible_MatchingBreakTypeAndSpotStartTimBeforeBreak_SpotIsRejected() { // Arrange Spot fakeSpot = SpotWithValidBreakTypeAndStartTimeFactory(); MoveSpotByMinutes(fakeSpot, -10); Break fakeBreak = BreakWithValidBreakTypeFactory(); var fakeSmoothBreak = new SmoothBreak(fakeBreak, 1); var service = CanAddSpotService.Factory(fakeSmoothBreak); // Act var result = service.IsSpotEligibleWhenRespectingSpotTime(fakeSpot); // Assert _ = result.Should().BeFalse(because: "the Break is after the allowed Spot time slot"); }
public static void RemoveSpotFromBreak( SmoothBreak smoothBreak, Spot spot, ICollection <Guid> spotIdsUsed, SponsorshipRestrictionService sponsorshipRestrictionService ) { smoothBreak.RemoveSpot(spot); if (spotIdsUsed.Contains(spot.Uid)) { _ = spotIdsUsed.Remove(spot.Uid); } sponsorshipRestrictionService.TriggerRecalculationOfAllowedRestrictionLimits( SpotAction.RemoveSpot, spot, smoothBreak.TheBreak ); }
/// <summary> /// Gets all restrictions that the spot conflicts with. /// </summary> public List <CheckClashExceptionResult> CheckClashExceptions( SmoothBreak smoothBreak, Spot spot) { var results = new List <CheckClashExceptionResult>(); foreach (ClashException clashException in _clashExceptions) { var action = CheckClashException(smoothBreak, spot, clashException); if (action == CheckClashExceptionActions.NoAction) { continue; } results.Add(new CheckClashExceptionResult(clashException)); } return(results); }
/// <summary> /// Calculates the factor score for product clashes at both child and /// parent level /// </summary> private double GetFactorScoreForProductClashes( SmoothBreak smoothBreak, IReadOnlyCollection <Spot> spots, IReadOnlyDictionary <Guid, SpotInfo> spotInfos, IReadOnlyDictionary <string, Product> productsByExternalRef, IReadOnlyDictionary <string, Clash> clashesByExternalRef, IProductClashChecker productClashChecker, IClashExposureCountService effectiveClashExposureCount) { var factorScoreCalculator = new ProductClashFactorScore(effectiveClashExposureCount); return(factorScoreCalculator.GetFactorScoreForProductClashes( smoothBreak.SmoothSpots.Select(s => s.Spot).ToList(), spots, spotInfos, productsByExternalRef, clashesByExternalRef, productClashChecker.GetProductClashesForSingleSpot )); }