Skip to content

Commit

Permalink
provide a unified impl for progress value
Browse files Browse the repository at this point in the history
  • Loading branch information
laolarou726 committed Nov 22, 2024
1 parent d0df8a4 commit 89dcaff
Show file tree
Hide file tree
Showing 22 changed files with 144 additions and 90 deletions.
4 changes: 2 additions & 2 deletions ProjBobcat/ProjBobcat/Class/Helper/DownloadHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public static async Task DownloadData(DownloadFile downloadFile, DownloadSetting

downloadFile.OnChanged(
averageSpeed,
1,
ProgressValue.FromDisplay(100),
responseLength,
responseLength);

Expand Down Expand Up @@ -483,7 +483,7 @@ public static async Task MultiPartDownloadTaskAsync(
if (downloadSettings.ShowDownloadProgressForPartialDownload)
downloadFile.OnChanged(
(double)addedAggregatedSpeed / addedAggregatedSpeedCount,
(double)addedBytesReceived / urlInfo.FileLength,
ProgressValue.Create(addedBytesReceived, urlInfo.FileLength),
addedBytesReceived,
urlInfo.FileLength);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class DownloadFile
/// </summary>
public event EventHandler<DownloadFileChangedEventArgs>? Changed;

internal void OnChanged(double speed, double progress, long bytesReceived, long totalBytes)
internal void OnChanged(double speed, ProgressValue progress, long bytesReceived, long totalBytes)
{
this.Changed?.Invoke(this, new DownloadFileChangedEventArgs
{
Expand Down
2 changes: 1 addition & 1 deletion ProjBobcat/ProjBobcat/Class/Model/ProgressReportBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class ProgressReportBase : IProgressReport
{
public event EventHandler<StageChangedEventArgs>? StageChangedEventDelegate;

protected void InvokeStatusChangedEvent(string currentStage, double progress)
protected void InvokeStatusChangedEvent(string currentStage, ProgressValue progress)
{
this.StageChangedEventDelegate?.Invoke(this, new StageChangedEventArgs
{
Expand Down
40 changes: 40 additions & 0 deletions ProjBobcat/ProjBobcat/Class/Model/ProgressValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Globalization;

namespace ProjBobcat.Class.Model;

/// <summary>
/// A unified impl for the progress value
/// <br/>
/// <b>Implicit convert this struct to <seealso cref="double"/> will get the value of <seealso cref="NormalizedValue"/> </b>
/// </summary>
/// <param name="NormalizedValue"></param>
public readonly record struct ProgressValue(double NormalizedValue) : IFormattable
{
/// <summary>
/// Display value for the progress, range usually in 0-100
/// </summary>
public double DisplayValue => this.NormalizedValue * 100;

public static implicit operator double(ProgressValue value) => value.DisplayValue;

public static ProgressValue Start => new (0);
public static ProgressValue Finished => new (1);

/// <summary>
/// Create a new progress base on <seealso cref="numerator"/> and <seealso cref="denominator"/>
/// </summary>
/// <param name="numerator"></param>
/// <param name="denominator"></param>
/// <returns></returns>
public static ProgressValue Create(double numerator, double denominator) => FromNormalized(numerator / denominator);
public static ProgressValue FromNormalized(double normalizedValue) => new (normalizedValue);
public static ProgressValue FromDisplay(double displayValue) => new (displayValue / 100);

public string ToString(string? format, IFormatProvider? formatProvider)
{
return NormalizedValue.ToString(format, formatProvider);
}

public override string ToString() => NormalizedValue.ToString(CultureInfo.CurrentCulture);
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class DefaultResourceCompleter : IResourceCompleter

this.OnResolveComplete(this, new GameResourceInfoResolveEventArgs
{
Progress = 0,
Progress = ProgressValue.Start,
Status = "正在进行资源检查"
});

Expand Down Expand Up @@ -104,7 +104,7 @@ void FireResolveEvent(object? sender, GameResourceInfoResolveEventArgs e)

this.OnResolveComplete(this, new GameResourceInfoResolveEventArgs
{
Progress = 100,
Progress = ProgressValue.Finished,
Status = "资源检查完成"
});

Expand Down Expand Up @@ -164,7 +164,7 @@ void OnCompleted(object? sender, DownloadFileCompletedEventArgs e)
this.DownloadFileCompletedEvent?.Invoke(sender, e);
}

void OnChanged(double progress, double speed)
void OnChanged(ProgressValue progress, double speed)
{
this.DownloadFileChangedEvent?.Invoke(this, new DownloadFileChangedEventArgs
{
Expand All @@ -183,7 +183,7 @@ void WhenCompleted(object? sender, DownloadFileCompletedEventArgs e)
var downloaded = Interlocked.Increment(ref this._totalDownloaded);
var needToDownload = Interlocked.Read(ref this._needToDownload);

this.OnChanged((double)downloaded / needToDownload, e.AverageSpeed);
this.OnChanged(ProgressValue.Create(downloaded, needToDownload), e.AverageSpeed);
this.OnCompleted(sender, e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public string Install()

public async Task<string> InstallTaskAsync()
{
this.InvokeStatusChangedEvent("开始安装", 0);
this.InvokeStatusChangedEvent("开始安装", ProgressValue.Start);

if (string.IsNullOrEmpty(this.RootPath))
throw new NullReferenceException("RootPath 字段为空");
Expand Down Expand Up @@ -76,7 +76,7 @@ public async Task<string> InstallTaskAsync()
else
DirectoryHelper.CleanDirectory(di.FullName);

this.InvokeStatusChangedEvent("生成版本总成", 70);
this.InvokeStatusChangedEvent("生成版本总成", ProgressValue.FromDisplay(70));

var resultModel = new RawVersionModel
{
Expand All @@ -93,11 +93,11 @@ public async Task<string> InstallTaskAsync()
var jsonContent = JsonSerializer.Serialize(resultModel, typeof(RawVersionModel),
new RawVersionModelContext(JsonHelper.CamelCasePropertyNamesSettings()));

this.InvokeStatusChangedEvent("将版本 Json 写入文件", 90);
this.InvokeStatusChangedEvent("将版本 Json 写入文件", ProgressValue.FromDisplay(95));

await File.WriteAllTextAsync(jsonPath, jsonContent);

this.InvokeStatusChangedEvent("安装完成", 100);
this.InvokeStatusChangedEvent("安装完成", ProgressValue.Finished);

return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()

#region 解析 Version.json

this.InvokeStatusChangedEvent("解析 Version.json", 0.1);
this.InvokeStatusChangedEvent("解析 Version.json", ProgressValue.FromDisplay(10));

var versionJsonEntry =
archive.Entries.FirstOrDefault(e =>
Expand Down Expand Up @@ -105,7 +105,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()

#region 解析 Install_profile.json

this.InvokeStatusChangedEvent("解析 Install_profile.json", 0.2);
this.InvokeStatusChangedEvent("解析 Install_profile.json", ProgressValue.FromDisplay(20));

var installProfileEntry =
archive.Entries.FirstOrDefault(e =>
Expand All @@ -124,7 +124,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()

#region 解析 Lzma

this.InvokeStatusChangedEvent("解析 Lzma", 0.4);
this.InvokeStatusChangedEvent("解析 Lzma", ProgressValue.FromDisplay(40));

var serverLzma = archive.Entries.FirstOrDefault(e =>
e.Key?.Equals("data/server.lzma", StringComparison.OrdinalIgnoreCase) ?? false);
Expand Down Expand Up @@ -174,7 +174,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()

#region 解压 Forge Jar

this.InvokeStatusChangedEvent("解压 Forge Jar", 0.5);
this.InvokeStatusChangedEvent("解压 Forge Jar", ProgressValue.FromDisplay(50));

var forgeJar = archive.Entries.FirstOrDefault(e =>
e.Key?.Equals($"maven/net/minecraftforge/forge/{forgeVersion}/forge-{forgeVersion}.jar",
Expand Down Expand Up @@ -272,7 +272,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()

#region 解析 Processor

this.InvokeStatusChangedEvent("解析 Processor", 1);
this.InvokeStatusChangedEvent("解析 Processor", ProgressValue.Finished);

string? ResolvePathRegex(string? val)
{
Expand Down Expand Up @@ -535,7 +535,8 @@ where lineSp[0].Equals("Main-Class", StringComparison.OrdinalIgnoreCase)
logSb.AppendLine(args.Data);

var data = args.Data;
var progress = (double)this._totalProcessed / this._needToProcess;

var progress = ProgressValue.Create(this._totalProcessed, this._needToProcess);
var dataStr = data.CropStr(40);

this.InvokeStatusChangedEvent($"{dataStr} <安装信息> ( {this._totalProcessed} / {this._needToProcess} )",
Expand All @@ -549,7 +550,7 @@ where lineSp[0].Equals("Main-Class", StringComparison.OrdinalIgnoreCase)
errSb.AppendLine(args.Data);

var data = args.Data ?? string.Empty;
var progress = (double)this._totalProcessed / this._needToProcess;
var progress = ProgressValue.Create(this._totalProcessed, this._needToProcess);
var dataStr = data.CropStr(40);

this.InvokeStatusChangedEvent($"{dataStr} <错误> ( {this._totalProcessed} / {this._needToProcess} )",
Expand Down Expand Up @@ -619,7 +620,8 @@ void WhenCompleted(object? sender, DownloadFileCompletedEventArgs e)

this._totalDownloaded++;

var progress = (double)this._totalDownloaded / this._needToDownload;

var progress = ProgressValue.Create(this._totalDownloaded, this._needToDownload);
var retryStr = file.RetryCount > 0 ? $"[重试 - {file.RetryCount}] " : string.Empty;

this.InvokeStatusChangedEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()
{
try
{
this.InvokeStatusChangedEvent("解压安装文件", 0.05);
this.InvokeStatusChangedEvent("解压安装文件", ProgressValue.Start);

using var reader = ArchiveFactory.Open(this.ForgeExecutablePath);
var profileEntry =
Expand Down Expand Up @@ -76,18 +76,18 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()
Succeeded = false
};

this.InvokeStatusChangedEvent("解压完成", 0.1);
this.InvokeStatusChangedEvent("解压完成", ProgressValue.FromDisplay(5));

await using var stream = profileEntry.OpenEntryStream();

this.InvokeStatusChangedEvent("解析安装文档", 0.35);
this.InvokeStatusChangedEvent("解析安装文档", ProgressValue.FromDisplay(35));

var profileModel = await JsonSerializer.DeserializeAsync(stream,
LegacyForgeInstallProfileContext.Default.LegacyForgeInstallProfile);
if (profileModel == null)
throw new ArgumentNullException(nameof(profileModel));

this.InvokeStatusChangedEvent("解析完成", 0.75);
this.InvokeStatusChangedEvent("解析完成", ProgressValue.FromDisplay(75));

var id = string.IsNullOrEmpty(this.CustomId) ? profileModel.VersionInfo.Id : this.CustomId;

Expand Down Expand Up @@ -121,7 +121,7 @@ public async Task<ForgeInstallResult> InstallForgeTaskAsync()
new LegacyForgeInstallVersionInfoContext(JsonHelper.CamelCasePropertyNamesSettings()));

await File.WriteAllTextAsync(jsonPath, versionJsonString);
this.InvokeStatusChangedEvent("文件写入完成", 1);
this.InvokeStatusChangedEvent("文件写入完成", ProgressValue.Finished);

return new ForgeInstallResult
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ public async Task<string> InstallTaskAsync()
if (this.VersionModel == null)
throw new NullReferenceException("VersionModel 不能为 null");

this.InvokeStatusChangedEvent("开始安装 LiteLoader", 0);
this.InvokeStatusChangedEvent("开始安装 LiteLoader", ProgressValue.Start);

var vl = new DefaultVersionLocator(this.RootPath, Guid.Empty);
var rawVersion = vl.ParseRawVersion(this.VersionModel.McVersion);

this.InvokeStatusChangedEvent("解析版本", 10);
this.InvokeStatusChangedEvent("解析版本", ProgressValue.FromDisplay(10));

if (rawVersion == null)
throw new UnknownGameNameException(this.VersionModel.McVersion);
Expand All @@ -57,7 +57,7 @@ public async Task<string> InstallTaskAsync()
var timeStamp = long.TryParse(this.VersionModel.Build.Timestamp, out var timeResult) ? timeResult : 0;
var time = TimeHelper.Unix11ToDateTime(timeStamp);

this.InvokeStatusChangedEvent("解析 Libraries", 30);
this.InvokeStatusChangedEvent("解析 Libraries", ProgressValue.FromDisplay(30));

var libraries = new List<Library>
{
Expand All @@ -77,7 +77,7 @@ public async Task<string> InstallTaskAsync()

libraries.AddRange(this.VersionModel.Build.Libraries);

this.InvokeStatusChangedEvent("Libraries 解析完成", 60);
this.InvokeStatusChangedEvent("Libraries 解析完成", ProgressValue.FromDisplay(60));

const string mainClass = "net.minecraft.launchwrapper.Launch";
var resultModel = new RawVersionModel
Expand Down Expand Up @@ -119,7 +119,7 @@ public async Task<string> InstallTaskAsync()

await File.WriteAllTextAsync(jsonPath, jsonContent);

this.InvokeStatusChangedEvent("LiteLoader 安装完成", 100);
this.InvokeStatusChangedEvent("LiteLoader 安装完成", ProgressValue.Finished);

return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using ProjBobcat.Class.Helper;
using ProjBobcat.Class.Model;
using ProjBobcat.Class.Model.CurseForge;
using ProjBobcat.Class.Model.Downloading;
using ProjBobcat.Exceptions;
Expand All @@ -33,7 +35,7 @@ public async Task InstallTaskAsync()
ArgumentException.ThrowIfNullOrEmpty(this.GameId);
ArgumentException.ThrowIfNullOrEmpty(this.RootPath);

this.InvokeStatusChangedEvent("开始安装", 0);
this.InvokeStatusChangedEvent("开始安装", ProgressValue.Start);

var manifest = await this.ReadManifestTask();

Expand Down Expand Up @@ -78,18 +80,18 @@ public async Task InstallTaskAsync()

urlBags.Add(downloadFile);

this.TotalDownloaded++;
this.NeedToDownload++;

var progress = (double)this.TotalDownloaded / this.NeedToDownload * 100;
var addedTotalDownloaded = Interlocked.Increment(ref this.TotalDownloaded);
var addedNeedToDownload = Interlocked.Increment(ref this.NeedToDownload);
var progress = ProgressValue.Create(addedTotalDownloaded, addedNeedToDownload);

this.InvokeStatusChangedEvent($"成功解析 MOD [{t.Item1}] 的下载地址",
progress);
}
catch (CurseForgeModResolveException e)
{
this.InvokeStatusChangedEvent($"MOD [{t.Item1}] 的下载地址解析失败,尝试手动拼接",
114514);
this.InvokeStatusChangedEvent(
$"MOD [{t.Item1}] 的下载地址解析失败,尝试手动拼接",
ProgressValue.FromDisplay(50));

var (guessed, df) = await this.TryGuessModDownloadLink(t.Item2, di.FullName);

Expand Down Expand Up @@ -119,10 +121,9 @@ public async Task InstallTaskAsync()

urlBags.Add(df);

this.TotalDownloaded++;
this.NeedToDownload++;

var progress = (double)this.TotalDownloaded / this.NeedToDownload * 100;
var addedTotalDownloaded = Interlocked.Increment(ref this.TotalDownloaded);
var addedNeedToDownload = Interlocked.Increment(ref this.NeedToDownload);
var progress = ProgressValue.Create(addedTotalDownloaded, addedNeedToDownload);

this.InvokeStatusChangedEvent($"成功解析 MOD [{t.Item1}] 的下载地址",
progress);
Expand Down Expand Up @@ -185,16 +186,17 @@ public async Task InstallTaskAsync()
? $"...{subPath[(subPathLength - 15)..]}"
: subPath;

this.InvokeStatusChangedEvent($"解压缩安装文件:{subPathName}",
(double)this.TotalDownloaded / this.NeedToDownload * 100);
var progress = ProgressValue.Create(this.TotalDownloaded, this.NeedToDownload);

this.InvokeStatusChangedEvent($"解压缩安装文件:{subPathName}", progress);

await using var fs = File.OpenWrite(path);
entry.WriteTo(fs);

this.TotalDownloaded++;
}

this.InvokeStatusChangedEvent("安装完成", 100);
this.InvokeStatusChangedEvent("安装完成", ProgressValue.Finished);
}

public async Task<CurseForgeManifestModel?> ReadManifestTask()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ protected void WhenCompleted(object? sender, DownloadFileCompletedEventArgs e)

this.TotalDownloaded++;

var progress = (double)this.TotalDownloaded / this.NeedToDownload * 100;
var progress = ProgressValue.Create(this.TotalDownloaded, this.NeedToDownload);
var retryStr = file.RetryCount > 0 ? $"[重试 - {file.RetryCount}] " : string.Empty;
var fileName = file.FileName.Length > 20
? $"{file.FileName[..20]}..."
Expand Down
Loading

0 comments on commit 89dcaff

Please sign in to comment.