diff --git a/Core.Tests/Utility/TimeInProgressEstimaterTests.cs b/Core.Tests/Utility/TimeInProgressEstimaterTests.cs index ac7c9d0..abfd594 100644 --- a/Core.Tests/Utility/TimeInProgressEstimaterTests.cs +++ b/Core.Tests/Utility/TimeInProgressEstimaterTests.cs @@ -13,15 +13,22 @@ namespace LeafWeb.Core.Tests.Utility [Test] public void EstimateTest() { - Func scaleFunc = i => i*i; + Func scaleFunc = i => i*60*10; - var obervations = - from i in Enumerable.Range(1, 10) - let time = scaleFunc(i) + //var obervations = + // from i in Enumerable.Range(1, 10) + // let time = scaleFunc(i) + // select Mock.Of(li => + // li.InputFiles.Count == i && + // li.TimeInProgress == TimeSpan.FromMinutes(time)); + + var obervations = + from d in data select Mock.Of(li => - li.InputFiles.Count == i && - li.TimeInProgress == TimeSpan.FromMinutes(time)); - + li.InputFiles.Count == d.Item1 && + li.TimeInProgress == TimeSpan.FromSeconds(d.Item2) + ); + var estimater = new TimeInProgressEstimater(obervations.ToArray()); Action est = i => @@ -31,8 +38,94 @@ namespace LeafWeb.Core.Tests.Utility Console.WriteLine($"{i} => {estimate}. {TimeSpan.FromMinutes(scaleFunc(i))}"); }; - for (var i = 1; i < 30; i++) + for (var i = 1; i < 100; i++) est(i); } + + private Tuple[] data = + { + Tuple.Create(3, 990.347), + Tuple.Create(11, 5688.136), + Tuple.Create(166, 243433.25), + Tuple.Create(156, 96585.35), + Tuple.Create(23, 205828.927), + Tuple.Create(10, 4679.583), + Tuple.Create(20, 28568.39), + Tuple.Create(3, 1456.104), + Tuple.Create(3, 1144.78), + Tuple.Create(23, 12356.24), + Tuple.Create(5, 10149.49), + Tuple.Create(10, 4832.93), + Tuple.Create(4, 1770.086), + Tuple.Create(8, 4727.98), + Tuple.Create(20, 35137.31), + Tuple.Create(20, 38265.414), + Tuple.Create(20, 23023.103), + Tuple.Create(20, 28994.213), + Tuple.Create(8, 6755.817), + Tuple.Create(20, 11458.047), + Tuple.Create(20, 13239.973), + Tuple.Create(1, 155.907), + Tuple.Create(1, 198.236), + Tuple.Create(4, 6171.793), + Tuple.Create(13, 6036.343), + Tuple.Create(13, 6287.683), + Tuple.Create(1, 230.48), + Tuple.Create(2, 3134.58), + Tuple.Create(15, 26254.85), + Tuple.Create(17, 10140.037), + Tuple.Create(10, 7622.307), + Tuple.Create(8, 9016.327), + Tuple.Create(9, 8037.403), + Tuple.Create(18, 14819.907), + Tuple.Create(4, 2744.767), + Tuple.Create(30, 26198.996), + Tuple.Create(27, 25819.637), + Tuple.Create(30, 17456.014), + Tuple.Create(28, 17611.16), + Tuple.Create(24, 8778.873), + Tuple.Create(1, 343.343), + Tuple.Create(2, 797.004), + Tuple.Create(1, 199.92), + Tuple.Create(24, 13000.967), + Tuple.Create(18, 15778.11), + Tuple.Create(5, 3511.834), + Tuple.Create(5, 1211.593), + Tuple.Create(5, 8895.523), + Tuple.Create(5, 3537.074), + Tuple.Create(5, 2411.197), + Tuple.Create(5, 11243.546), + Tuple.Create(6, 3967.287), + Tuple.Create(6, 3912.07), + Tuple.Create(5, 2406.013), + Tuple.Create(5, 11237.71), + Tuple.Create(35, 16774.884), + Tuple.Create(31, 12828.044), + Tuple.Create(30, 15379.2), + Tuple.Create(30, 15139.8), + Tuple.Create(36, 59509.324), + Tuple.Create(33, 36650.247), + Tuple.Create(35, 17443.134), + Tuple.Create(32, 17103.803), + Tuple.Create(32, 23901.747), + Tuple.Create(31, 17996.223), + Tuple.Create(36, 35667.134), + Tuple.Create(33, 25839.96), + Tuple.Create(30, 30598.057), + Tuple.Create(1, 559.94), + Tuple.Create(30, 37881.45), + Tuple.Create(1, 1536.64), + Tuple.Create(1, 1635.797), + Tuple.Create(6, 5198.684), + Tuple.Create(30, 33436.844), + Tuple.Create(30, 46370.277), + Tuple.Create(29, 2054.907), + Tuple.Create(24, 1898.857), + Tuple.Create(24, 2658.23), + Tuple.Create(40, 3984.13), + Tuple.Create(29, 4258.67), + Tuple.Create(24, 3210.917), + Tuple.Create(24, 2931.43) + }; } } \ No newline at end of file diff --git a/Core/DAL/DataService.cs b/Core/DAL/DataService.cs index 776d92a..caae8bf 100644 --- a/Core/DAL/DataService.cs +++ b/Core/DAL/DataService.cs @@ -80,6 +80,16 @@ namespace LeafWeb.Core.DAL select s).Max(s => s.DateTime)); } + public IEnumerable GetLeafInputRecentlyCompleted(int count) + { + return + _db.LeafInputs + .Where(li => li.CurrentStatus == LeafInputStatusType.Complete) + .Take(count) + .ToList() + .Where(li => li.OutputErrorMessage == null); + } + public LeafInput GetLeafInput(int id) { return _db.LeafInputs.FirstOrDefault(li => li.Id == id); diff --git a/Core/Utility/TimeInProgressEstimater.cs b/Core/Utility/TimeInProgressEstimater.cs index 6b5ce01..d11c896 100644 --- a/Core/Utility/TimeInProgressEstimater.cs +++ b/Core/Utility/TimeInProgressEstimater.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using LeafWeb.Core.Entities; using MathNet.Numerics; @@ -23,7 +24,15 @@ namespace LeafWeb.Core.Utility _yData = yData.ToArray(); } - private Func FitFunc => Fit.PolynomialFunc(_xData, _yData, 3); + private static Func Positivize => i => i <= 0 ? 1 : i; + + private IEnumerable Div => _xData.Zip(_yData, (x, y) => y/x); + + private Func AverageFitFunc => i => Div.Average()*i; + + private Func LineFitFunc => Fit.LineFunc(_xData, _yData); + + private Func FitFunc => i => (Positivize(LineFitFunc(i)) + AverageFitFunc(i))/2; public TimeSpan EstimateTimeInProgress(ILeafInput leafInput) { @@ -32,7 +41,10 @@ namespace LeafWeb.Core.Utility public TimeSpan EstimateTimeInProgress(int inputFileCount) { - return ConvertToTimeSpan(FitFunc(inputFileCount)); + var estimate = FitFunc(inputFileCount); + if (estimate <= 0) + estimate = 1; + return ConvertToTimeSpan(estimate); } private static double ConvertFromTimeSpan(TimeSpan timeSpan) @@ -42,16 +54,19 @@ namespace LeafWeb.Core.Utility private static TimeSpan ConvertToTimeSpan(double estimate) { - int int32; + return TimeSpan.FromSeconds(ConvertToInt32Guarded(estimate)); + } + + private static Func ConvertToInt32Guarded => d => + { try { - int32 = Convert.ToInt32(estimate); + return Convert.ToInt32(d); } catch (OverflowException) { - int32 = int.MaxValue; + return int.MaxValue; } - return TimeSpan.FromSeconds(int32); - } + }; } } diff --git a/WebCms/App_Data/Models/all.dll.path b/WebCms/App_Data/Models/all.dll.path index bc81773..5ad93ea 100644 --- a/WebCms/App_Data/Models/all.dll.path +++ b/WebCms/App_Data/Models/all.dll.path @@ -1 +1 @@ -C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.g_xi0dfe.dll \ No newline at end of file +C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.re2ngwmg.dll \ No newline at end of file diff --git a/WebCms/Controllers/QueueController.cs b/WebCms/Controllers/QueueController.cs index 9de1bc1..1a0ed5d 100644 --- a/WebCms/Controllers/QueueController.cs +++ b/WebCms/Controllers/QueueController.cs @@ -35,8 +35,8 @@ namespace LeafWeb.WebCms.Controllers } // completed leaf input for computing runtime statistics - var completedLeafInput = DataService.GetLeafInputsOrdered().Where(li => li.CurrentStatus == LeafInputStatusType.Complete); - var timeInProgressEstimater = new TimeInProgressEstimater(completedLeafInput.Take(20)); + var completedLeafInput = DataService.GetLeafInputRecentlyCompleted(100); + var timeInProgressEstimater = new TimeInProgressEstimater(completedLeafInput); var serviceDescription = ServiceDescription(); @@ -49,6 +49,14 @@ namespace LeafWeb.WebCms.Controllers return View(queueViewModel); } + public ActionResult LeafInputStatistics() + { + var data = + from li in DataService.GetLeafInputRecentlyCompleted(100) + select $"{li.InputFiles.Count}, {li.TimeInProgress.TotalSeconds}"; + return Content(string.Join("
", data)); + } + public ActionResult Search(string query) { var nameValueCollection = new NameValueCollection {{"query", query}}; diff --git a/WebCms/Views/Queue/Details.cshtml b/WebCms/Views/Queue/Details.cshtml index 101c8d5..e297428 100644 --- a/WebCms/Views/Queue/Details.cshtml +++ b/WebCms/Views/Queue/Details.cshtml @@ -18,6 +18,12 @@ Download ToUser + + Download NotToUser + + @using (Html.BeginUmbracoForm( "SendUserDownloadLink", null, new { @class = "confirm", confirm_msg = "Confirm sending email to user" })) { diff --git a/WebCms/Views/Queue/Index.cshtml b/WebCms/Views/Queue/Index.cshtml index 0c63898..8d65e1e 100644 --- a/WebCms/Views/Queue/Index.cshtml +++ b/WebCms/Views/Queue/Index.cshtml @@ -10,7 +10,7 @@
Service description: @Model.ServerDescription
Est. processing time by LeafInput size - - < 1: @Model.TimeInProgressEstimater.EstimateTimeInProgress(1).ToRoundedReadableString() + 1: @Model.TimeInProgressEstimater.EstimateTimeInProgress(1).ToRoundedReadableString() 10: @Model.TimeInProgressEstimater.EstimateTimeInProgress(10).ToRoundedReadableString() 100: @Model.TimeInProgressEstimater.EstimateTimeInProgress(100).ToRoundedReadableString()
@@ -59,7 +59,16 @@ if (leafInput.IsPending) } else { + @Html.Partial("DisplayTemplates/_LeafInputStatus", leafInput.CurrentStatus.ToString()) + @if (leafInput.OutputErrorMessage != null) + { + + } else if (leafInput.OutputWarningMessage != null) + { + + } + } }