PlotDirector/PlotLine/ViewModels/StoryIntelligenceGlobalProgressViewModels.cs

69 lines
2.9 KiB
C#

namespace PlotLine.ViewModels;
public sealed class StoryIntelligenceGlobalProgressViewModel
{
public IReadOnlyList<StoryIntelligenceGlobalProgressBookViewModel> Books { get; init; } = [];
public bool HasActiveWork => Books.Any(book => book.HasActiveRuns);
public int ActiveBookCount => Books.Count(book => book.HasActiveRuns);
public int ActiveRunCount => Books.Sum(book => book.PendingRunCount + book.RunningRunCount);
public int TotalDetectedScenes => Books.Sum(book => book.TotalDetectedScenes);
public int CompletedScenes => Books.Sum(book => book.CompletedScenes);
public int FailedScenes => Books.Sum(book => book.FailedScenes);
public int ProgressPercent => TotalDetectedScenes <= 0
? 0
: Math.Clamp(Convert.ToInt32(Math.Round(CompletedScenes * 100m / TotalDetectedScenes)), 0, 100);
public string SummaryText => ActiveBookCount switch
{
0 => string.Empty,
1 => Books.First(book => book.HasActiveRuns).SummaryText,
_ => $"{ActiveBookCount:N0} books analysing"
};
}
public sealed class StoryIntelligenceGlobalProgressBookViewModel
{
public int? ProjectID { get; init; }
public int? BookID { get; init; }
public string BookTitle { get; init; } = "Book";
public int RunCount { get; init; }
public int PendingRunCount { get; init; }
public int RunningRunCount { get; init; }
public int CompletedRunCount { get; init; }
public int FailedRunCount { get; init; }
public int TotalDetectedScenes { get; init; }
public int CompletedScenes { get; init; }
public int FailedScenes { get; init; }
public long TotalDurationMs { get; init; }
public DateTime UpdatedUtc { get; init; }
public bool HasActiveRuns => PendingRunCount > 0 || RunningRunCount > 0;
public bool HasFailures => FailedRunCount > 0 || FailedScenes > 0;
public int ProgressPercent => TotalDetectedScenes <= 0
? 0
: Math.Clamp(Convert.ToInt32(Math.Round(CompletedScenes * 100m / TotalDetectedScenes)), 0, 100);
public string SummaryText => $"{BookTitle}: {CompletedScenes:N0}/{Math.Max(TotalDetectedScenes, CompletedScenes):N0} scenes";
public string EstimatedRemaining => EstimateRemaining(TotalDurationMs, CompletedScenes, TotalDetectedScenes);
private static string EstimateRemaining(long elapsedMs, int completedScenes, int totalScenes)
{
if (totalScenes <= 0 || completedScenes <= 0)
{
return "Calculating";
}
if (completedScenes >= totalScenes)
{
return "Finalising";
}
var averageSceneMs = elapsedMs / Math.Max(1, completedScenes);
var remaining = TimeSpan.FromMilliseconds(averageSceneMs * (totalScenes - completedScenes));
if (remaining.TotalMinutes >= 1)
{
return $"{Math.Max(1, (int)Math.Round(remaining.TotalMinutes)):N0} min";
}
return $"{Math.Max(1, (int)Math.Round(remaining.TotalSeconds)):N0} sec";
}
}