Esempio n. 1
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);
        }
Esempio n. 2
0
        private void LogBestBreakFactorScore(
            SmoothPass smoothPass,
            SmoothPassDefaultIteration smoothPassIteration,
            SmoothBreak smoothBreak,
            IReadOnlyCollection <Spot> spots,
            decimal breakScore,
            BestBreakFactorGroup bestBreakFactorGroup,
            string scoreDebug,
            string type)
        {
            var spotsDuration = Duration.Zero;

            foreach (var spot in spots)
            {
                spotsDuration = spotsDuration.Plus(spot.SpotLength);
            }

            string spotList = SpotUtilities.GetSpotDetailsListString(spots);

            var message = new StringBuilder(128);

            _ = message
                .AppendFormat("Break={0}; ", smoothBreak.TheBreak.ExternalBreakRef)
                .AppendFormat("BreakDur={0} sec(s);", ((int)smoothBreak.TheBreak.Duration.ToTimeSpan().TotalSeconds).ToString())
                .AppendFormat("Avail={0}s;", ((int)smoothBreak.RemainingAvailability.ToTimeSpan().TotalSeconds).ToString())
                .AppendFormat("SpotsDetails={0}; ", spotList)
                .AppendFormat("SpotsLength={0}s; ", ((int)spotsDuration.ToTimeSpan().TotalSeconds).ToString())
                .AppendFormat("ScoreDebug={0}; ", scoreDebug)
                .AppendFormat("Type={0}", type)
            ;

            _smoothDiagnostics.LogBestBreakFactorMessage(
                smoothPass,
                smoothPassIteration,
                bestBreakFactorGroup,
                smoothBreak.TheBreak,
                spots,
                breakScore,
                message.ToString());
        }
        /// <summary>
        /// Exports passes and iterations
        /// </summary>
        public void ExportPasses(string file)
        {
            _ = Directory.CreateDirectory(Path.GetDirectoryName(file));

            if (File.Exists(file))
            {
                File.Delete(file);
            }

            using (var writer = new StreamWriter(file, true))
            {
                // Write headers
                writer.WriteLine(string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}{0}{7}{0}{8}{0}{9}{0}{10}{0}{11}{0}{12}{0}{13}{0}{14}{0}{15}{0}{16}{0}{17}{0}{18}{0}{19}{0}{20}{0}{21}{0}{22}",
                                               _delimiter, "ID", "PassSequence", "PassType",
                                               "Pass-BreakRequests", "Pass-CanSplitMultipartSpots", "Pass-ClientPicked", "Pass-HasMultipartSpots",
                                               "Pass-HasProductClashCode", "Pass-HasSpotEndTime", "Pass-Preemptable", "Pass-Sponsored",
                                               "Iteration-Sequence",
                                               "Iteration-SpotFilter-HasSponsoredSpots", "Iteration-SpotFilter-HasBreakRequest", "Iteration-SpotFilter-HasFIBOrLIBRequest",
                                               "Iteration-RequestedBreakPositionRules", "Iteration-RequestedPositionInBreakRules",
                                               "Iteration-ProductClashRules",
                                               "Iteration-RespectCampaignClash", "Iteration-RespectClashExceptions",
                                               "Iteration-RespectRestrictions", "Iteration-RespectSpotTime"));

                int totalItemCount = 0;

                foreach (var pass in _smoothConfiguration.Passes.OrderBy(p => p.Sequence))
                {
                    if (pass is SmoothPassDefault smoothPassDefault)
                    {
                        foreach (var iterationRecord in _smoothConfiguration.IterationRecords
                                 .Where(ir =>
                                        ir.PassSequences.Contains(smoothPassDefault.Sequence) &&
                                        ir.PassDefaultIteration != null)
                                 )
                        {
                            SmoothPassDefaultIteration passDefaultIteration = iterationRecord.PassDefaultIteration;

                            var breakRequestsString = new StringBuilder();

                            if (smoothPassDefault.BreakRequests == null)
                            {
                                _ = breakRequestsString.Append("Any");
                            }
                            else
                            {
                                foreach (var breakRequest in smoothPassDefault.BreakRequests)
                                {
                                    AddToBreakRequestsString(breakRequestsString, breakRequest);
                                }
                            }

                            totalItemCount++;
                            writer.WriteLine(string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}{0}{7}{0}{8}{0}{9}{0}{10}{0}{11}{0}{12}{0}{13}{0}{14}{0}{15}{0}{16}{0}{17}{0}{18}{0}{19}{0}{20}{0}{21}{0}{22}",
                                                           _delimiter, totalItemCount, smoothPassDefault.Sequence, "Default",
                                                           breakRequestsString.ToString(), smoothPassDefault.CanSplitMultipartSpots.ToString(),
                                                           "True", // ClientPicked
                                                           smoothPassDefault.HasMultipartSpots == null ? "Any" : smoothPassDefault.HasMultipartSpots.ToString(),
                                                           smoothPassDefault.HasProductClashCode == null ? "Any" : smoothPassDefault.HasProductClashCode.ToString(),
                                                           smoothPassDefault.HasSpotEndTime == null ? "Any" : smoothPassDefault.HasSpotEndTime.ToString(),
                                                           smoothPassDefault.Preemptable == null ? "Any" : smoothPassDefault.Preemptable.ToString(),
                                                           smoothPassDefault.Sponsored == null ? "Any" : smoothPassDefault.Sponsored.ToString(),
                                                           passDefaultIteration.Sequence,
                                                           iterationRecord.SpotsCriteria.HasSponsoredSpots == null ? "Any" : iterationRecord.SpotsCriteria.HasSponsoredSpots.ToString(),
                                                           iterationRecord.SpotsCriteria.HasBreakRequest == null ? "Any" : iterationRecord.SpotsCriteria.HasBreakRequest.ToString(),
                                                           iterationRecord.SpotsCriteria.HasFIBORLIBRequests == null ? "Any" : iterationRecord.SpotsCriteria.HasFIBORLIBRequests.ToString(),
                                                           passDefaultIteration.BreakPositionRules, passDefaultIteration.RequestedPositionInBreakRules,
                                                           passDefaultIteration.ProductClashRules, passDefaultIteration.RespectCampaignClash,
                                                           passDefaultIteration.RespectClashExceptions, passDefaultIteration.RespectRestrictions, passDefaultIteration.RespectSpotTime));
                        }
                    }
                    else if (pass is SmoothPassUnplaced smoothPassUnplaced)
                    {
                        foreach (var iterationRecord in _smoothConfiguration.IterationRecords
                                 .Where(ir =>
                                        ir.PassSequences.Contains(smoothPassUnplaced.Sequence) &&
                                        ir.PassUnplacedIteration != null)
                                 )
                        {
                            SmoothPassUnplacedIteration passUnplacedIteration = iterationRecord.PassUnplacedIteration;

                            totalItemCount++;
                            writer.WriteLine(string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}{0}{7}{0}{8}{0}{9}{0}{10}{0}{11}{0}{12}{0}{13}{0}{14}{0}{15}{0}{16}{0}{17}{0}{18}{0}{19}{0}{20}{0}{21}{0}{22}",
                                                           _delimiter, totalItemCount, smoothPassUnplaced.Sequence, "Unplaced",
                                                           "Any", "Any", "Any", "Any", "Any", "Any", "Any", "Any",
                                                           passUnplacedIteration.Sequence,
                                                           iterationRecord.SpotsCriteria.HasSponsoredSpots == null ? "Any" : iterationRecord.SpotsCriteria.HasSponsoredSpots.ToString(),
                                                           iterationRecord.SpotsCriteria.HasBreakRequest == null ? "Any" : iterationRecord.SpotsCriteria.HasBreakRequest.ToString(),
                                                           iterationRecord.SpotsCriteria.HasFIBORLIBRequests == null ? "Any" : iterationRecord.SpotsCriteria.HasFIBORLIBRequests.ToString(),
                                                           "", "",
                                                           passUnplacedIteration.ProductClashRule, passUnplacedIteration.RespectCampaignClash,
                                                           passUnplacedIteration.RespectClashExceptions, passUnplacedIteration.RespectRestrictions, passUnplacedIteration.RespectSpotTime));
                        }
                    }
                }

                writer.Flush();
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Returns best break to add spot(s) to.
        /// </summary>
        public BestBreakResult GetBestBreak(
            SmoothPass smoothPass,
            SmoothPassDefaultIteration smoothPassIteration,
            IReadOnlyCollection <BestBreakFactorGroup> bestBreakFactorGroups,
            IReadOnlyCollection <SmoothBreak> validSmoothBreaks,
            IReadOnlyCollection <Spot> spotsToPlace,
            IReadOnlyDictionary <Guid, SpotInfo> spotInfos,
            IReadOnlyDictionary <string, Clash> clashesByExternalRef,
            IReadOnlyDictionary <string, Product> productsByExternalRef,
            IReadOnlyCollection <SmoothBreak> progSmoothBreaks,
            out BestBreakFactorGroup usedBestBreakFactorGroup)
        {
            var bestBreakResult = new BestBreakResult();

            usedBestBreakFactorGroup = null;

            string breakDetailsListString = BreakUtilities.GetListOfBreakExternalReferences(
                "; ",
                validSmoothBreaks.Select(sb => sb.TheBreak).ToList());

            // Get spot details list as string
            string spotDetailsListString = SpotUtilities.GetSpotDetailsListString(spotsToPlace);

            // Check each group in priority order
            foreach (var bestBreakFactorGroup in bestBreakFactorGroups.OrderBy(g => g.Sequence))
            {
                _smoothDiagnostics.LogBestBreakFactorMessage(
                    smoothPass,
                    smoothPassIteration,
                    bestBreakFactorGroup,
                    null,
                    spotsToPlace,
                    null,
                    $"Checking best break factor group (Breaks={breakDetailsListString}; Spots={spotDetailsListString})"
                    );

                // Set all breaks to check
                var smoothBreaksRemaining = new List <SmoothBreak>();
                smoothBreaksRemaining.AddRange(validSmoothBreaks);

                // Generate unique random score for each break so that we can
                // pick a random break if necessary.
                IReadOnlyCollection <double> randomScoreByBreak = GetRandomScoreByBreak(
                    progSmoothBreaks,
                    uniqueScore: true);

                // Calculate scores for each break, determine best score
                var     scoreByBreak   = new Dictionary <SmoothBreak, decimal>();
                decimal bestBreakScore = -1;

                foreach (var smoothBreak in smoothBreaksRemaining)
                {
                    var(breakScore, scoreDebug) = _bestBreakFactorForGroupService
                                                  .GetBestBreakFactorScoreForGroup(
                        smoothBreak,
                        spotsToPlace,
                        spotInfos,
                        clashesByExternalRef,
                        productsByExternalRef,
                        progSmoothBreaks,
                        randomScoreByBreak,
                        bestBreakFactorGroup,
                        _smoothResources
                        );

                    LogBestBreakFactorScore(
                        smoothPass,
                        smoothPassIteration,
                        smoothBreak,
                        spotsToPlace,
                        breakScore,
                        bestBreakFactorGroup,
                        "Main",
                        scoreDebug
                        );

                    scoreByBreak.Add(smoothBreak, breakScore);

                    if (breakScore > bestBreakScore || bestBreakScore == -1)
                    {
                        bestBreakScore = breakScore;
                    }
                }

                if (bestBreakScore > 0)   // At least one break has a non-zero score
                {
                    // Remove all breaks with score less than the best score
                    var smoothBreaksToRemove = new List <SmoothBreak>();
                    foreach (var smoothBreak in smoothBreaksRemaining)
                    {
                        if (scoreByBreak[smoothBreak] < bestBreakScore)
                        {
                            smoothBreaksToRemove.Add(smoothBreak);
                        }
                    }

                    while (smoothBreaksToRemove.Count > 0)
                    {
                        _ = smoothBreaksRemaining.Remove(smoothBreaksToRemove[0]);
                        smoothBreaksToRemove.RemoveAt(0);
                    }

                    // Single break with best score, return it
                    if (smoothBreaksRemaining.Count == 1)
                    {
                        _smoothDiagnostics.LogBestBreakFactorMessage(
                            smoothPass,
                            smoothPassIteration,
                            bestBreakFactorGroup,
                            smoothBreaksRemaining[0].TheBreak,
                            spotsToPlace,
                            bestBreakScore,
                            $"Using single break which has best score (Spots={spotDetailsListString})"
                            );

                        usedBestBreakFactorGroup    = bestBreakFactorGroup;
                        bestBreakResult.Score       = bestBreakScore;
                        bestBreakResult.SmoothBreak = smoothBreaksRemaining[0];

                        return(bestBreakResult);
                    }

                    // Multiple breaks with best score, determine what we do
                    if (smoothBreaksRemaining.Count > 1)
                    {
                        switch (bestBreakFactorGroup.SameBreakGroupScoreAction)
                        {
                        // Check next group, our default and so no action
                        // required here
                        case SameBreakGroupScoreActions.CheckNextGroup:
                            _smoothDiagnostics.LogBestBreakFactorMessage(
                                smoothPass,
                                smoothPassIteration,
                                bestBreakFactorGroup,
                                null,
                                spotsToPlace,
                                null,
                                "CheckNextGroup: Need to check next group"
                                );
                            break;

                        // Check single factor to identify single break
                        case SameBreakGroupScoreActions.UseSingleBreakFactorIfBestScoreIsNonZero:
                            // Calculate score for each remaining break
                            _smoothDiagnostics.LogBestBreakFactorMessage(
                                smoothPass,
                                smoothPassIteration,
                                bestBreakFactorGroup,
                                null,
                                spotsToPlace,
                                null,
                                $"UseSingleBreakFactorIfBestScoreIsNonZero: Finding break for single break factor score for group (BreaksRemaining={smoothBreaksRemaining.Count.ToString()})"
                                );

                            var     scoreByBreak2   = new Dictionary <SmoothBreak, decimal>();
                            decimal bestBreakScore2 = -1;

                            foreach (var smoothBreak in smoothBreaksRemaining)
                            {
                                decimal breakScore2 = _bestBreakFactorService
                                                      .GetBestBreakFactorScoreForFactor(
                                    smoothBreak,
                                    spotsToPlace,
                                    spotInfos,
                                    clashesByExternalRef,
                                    productsByExternalRef,
                                    progSmoothBreaks,
                                    randomScoreByBreak,
                                    bestBreakFactorGroup.SameBreakGroupScoreFactor,
                                    _smoothResources
                                    );

                                var scoreDebug = $"UseSingleBreakFactorIfBestScoreIsNonZero: {bestBreakFactorGroup.SameBreakGroupScoreFactor.Factor.ToString()}={breakScore2.ToString("0.000000000000000000000000000000")}";

                                LogBestBreakFactorScore(
                                    smoothPass,
                                    smoothPassIteration,
                                    smoothBreak,
                                    spotsToPlace,
                                    breakScore2,
                                    bestBreakFactorGroup,
                                    "",
                                    scoreDebug
                                    );

                                scoreByBreak2.Add(smoothBreak, breakScore2);
                                if (breakScore2 > bestBreakScore2 || bestBreakScore2 == -1)
                                {
                                    bestBreakScore2 = breakScore2;
                                }
                            }

                            // Remove all but the break with the best score
                            var smoothBreaksToRemove2 = new List <SmoothBreak>();
                            foreach (var smoothBreak in smoothBreaksRemaining)
                            {
                                if (scoreByBreak2[smoothBreak] < bestBreakScore2)
                                {
                                    smoothBreaksToRemove2.Add(smoothBreak);
                                }
                            }

                            while (smoothBreaksToRemove2.Count > 0)
                            {
                                _ = smoothBreaksRemaining.Remove(smoothBreaksToRemove2[0]);
                                smoothBreaksToRemove2.RemoveAt(0);
                            }

                            // Return first break Sanity check, if no break
                            // then check next group
                            if (smoothBreaksRemaining.Count > 0)
                            {
                                _smoothDiagnostics.LogBestBreakFactorMessage(
                                    smoothPass,
                                    smoothPassIteration,
                                    bestBreakFactorGroup,
                                    smoothBreaksRemaining[0].TheBreak,
                                    spotsToPlace,
                                    null,
                                    string.Format("UseSingleBreakFactorIfBestScoreIsNonZero: Found break for single break factor score for group (Spots={0}; BreaksRemaining={1})", spotDetailsListString, smoothBreaksRemaining.Count)
                                    );

                                usedBestBreakFactorGroup    = bestBreakFactorGroup;
                                bestBreakResult.Score       = bestBreakScore2;
                                bestBreakResult.SmoothBreak = smoothBreaksRemaining[0];
                                return(bestBreakResult);
                            }
                            else
                            {
                                _smoothDiagnostics.LogBestBreakFactorMessage(
                                    smoothPass,
                                    smoothPassIteration,
                                    bestBreakFactorGroup,
                                    null,
                                    spotsToPlace,
                                    null,
                                    string.Format("UseSingleBreakFactorIfBestScoreIsNonZero: WARNING: Not found break for single break factor score for group (Spots={0}; BreaksRemaining={1})", spotDetailsListString, smoothBreaksRemaining.Count)
                                    );
                            }

                            break;
                        }
                    }
                }
                else    // No break has a non-zero score, check next group
                {
                    _smoothDiagnostics.LogBestBreakFactorMessage(
                        smoothPass,
                        smoothPassIteration,
                        bestBreakFactorGroup,
                        null,
                        spotsToPlace,
                        null,
                        "No breaks with highest score, checking next group"
                        );
                }
            }

            _smoothDiagnostics.LogBestBreakFactorMessage(
                smoothPass,
                smoothPassIteration,
                null,
                null,
                spotsToPlace,
                null,
                "No best break for spots"
                );

            // All groups checked, no best break, shouldn't really happen,
            // possibly bad configuration
            return(bestBreakResult);
        }