109 lines
4.8 KiB
C#
109 lines
4.8 KiB
C#
using PlotLine.Models;
|
|
|
|
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 TotalExpectedScenes => Books.Sum(book => book.TotalExpectedScenes);
|
|
public int TotalDetectedScenes => TotalExpectedScenes;
|
|
public int CompletedScenes => Books.Sum(book => book.CompletedScenes);
|
|
public int FailedScenes => Books.Sum(book => book.FailedScenes);
|
|
public int ActiveScenes => Books.Sum(book => book.ActiveScenes);
|
|
public int ProgressPercent => TotalExpectedScenes <= 0
|
|
? 0
|
|
: Math.Clamp(Convert.ToInt32(Math.Round(CompletedScenes * 100m / TotalExpectedScenes)), 0, 100);
|
|
public DateTime? UpdatedUtc => Books.Count == 0 ? null : Books.Max(book => book.UpdatedUtc);
|
|
public string Status => Books.Any(book => book.Status == "Finalising")
|
|
? "Finalising"
|
|
: Books.Any(book => book.HasActiveRuns)
|
|
? StoryIntelligenceRunStatuses.Running
|
|
: Books.Any(book => book.HasFailures)
|
|
? StoryIntelligenceRunStatuses.CompletedWithWarnings
|
|
: StoryIntelligenceRunStatuses.Completed;
|
|
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 TotalExpectedScenes { get; init; }
|
|
public int TotalDetectedScenes => TotalExpectedScenes;
|
|
public int CompletedScenes { get; init; }
|
|
public int FailedScenes { get; init; }
|
|
public int ActiveScenes { get; init; }
|
|
public string Status { get; init; } = StoryIntelligenceRunStatuses.Pending;
|
|
public long TotalDurationMs { get; init; }
|
|
public DateTime UpdatedUtc { get; init; }
|
|
public IReadOnlyList<StoryIntelligenceGlobalProgressRunViewModel> Runs { get; init; } = [];
|
|
|
|
public bool HasActiveRuns => PendingRunCount > 0
|
|
|| RunningRunCount > 0
|
|
|| string.Equals(Status, "Finalising", StringComparison.OrdinalIgnoreCase);
|
|
public bool HasFailures => FailedRunCount > 0 || FailedScenes > 0;
|
|
public int ProgressPercent => TotalExpectedScenes <= 0
|
|
? 0
|
|
: Math.Clamp(Convert.ToInt32(Math.Round(CompletedScenes * 100m / TotalExpectedScenes)), 0, 100);
|
|
public string SummaryText => $"{BookTitle}: {CompletedScenes:N0}/{Math.Max(TotalExpectedScenes, CompletedScenes):N0} scenes";
|
|
public string EstimatedRemaining => Status == "Finalising"
|
|
? "Finalising"
|
|
: EstimateRemaining(TotalDurationMs, CompletedScenes, FailedScenes, TotalExpectedScenes);
|
|
|
|
private static string EstimateRemaining(long elapsedMs, int completedScenes, int failedScenes, int totalScenes)
|
|
{
|
|
if (totalScenes <= 0 || completedScenes <= 0)
|
|
{
|
|
return "Calculating";
|
|
}
|
|
|
|
var remainingScenes = Math.Max(0, totalScenes - completedScenes - failedScenes);
|
|
if (remainingScenes == 0)
|
|
{
|
|
return "Finalising";
|
|
}
|
|
|
|
var averageSceneMs = elapsedMs / Math.Max(1, completedScenes);
|
|
var remaining = TimeSpan.FromMilliseconds(averageSceneMs * remainingScenes);
|
|
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";
|
|
}
|
|
}
|
|
|
|
public sealed class StoryIntelligenceGlobalProgressRunViewModel
|
|
{
|
|
public int RunID { get; init; }
|
|
public int? ProjectID { get; init; }
|
|
public int? BookID { get; init; }
|
|
public string BookTitle { get; init; } = "Book";
|
|
public string Status { get; init; } = StoryIntelligenceRunStatuses.Pending;
|
|
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 IsTerminal => Status is StoryIntelligenceRunStatuses.Completed
|
|
or StoryIntelligenceRunStatuses.CompletedWithWarnings
|
|
or StoryIntelligenceRunStatuses.Failed
|
|
or StoryIntelligenceRunStatuses.Cancelled;
|
|
}
|