-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBattleReport.cs
More file actions
118 lines (110 loc) · 5.4 KB
/
Copy pathBattleReport.cs
File metadata and controls
118 lines (110 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System.Globalization;
using System.Text;
using System.Text.Json;
namespace XISOSharp.BattleTests;
/// <summary>Writes the battle report (txt + json) under BattleReports\.</summary>
internal static class BattleReport
{
public static void Write(BattleSession s, IReadOnlyList<string> picked)
{
try
{
string outDir = Path.Combine(Directory.GetCurrentDirectory(), "BattleReports");
Directory.CreateDirectory(outDir);
// Sub-second + PID component so concurrent runs never overwrite each
// other's reports (second-granularity stamps collide).
string stamp = DateTime.Now.ToString("yyyyMMdd_HHmmss_fff", CultureInfo.InvariantCulture)
+ "_" + Environment.ProcessId.ToString(CultureInfo.InvariantCulture);
string txtPath = Path.Combine(outDir, $"battle_{stamp}.txt");
string jsonPath = Path.Combine(outDir, $"battle_{stamp}.json");
File.WriteAllText(txtPath, BuildText(s, picked, stamp), new UTF8Encoding(false));
Console.WriteLine($"Report: {txtPath}");
File.WriteAllText(jsonPath, BuildJson(s, picked, stamp), new UTF8Encoding(false));
Console.WriteLine($" {jsonPath}");
}
catch (Exception ex)
{
Console.WriteLine($"[WARN] Failed to write reports: {ex.Message}");
}
}
private static string BuildText(BattleSession s, IReadOnlyList<string> picked, string stamp)
{
StringBuilder w = new();
w.AppendLine(CultureInfo.InvariantCulture, $"XISOSharp Battle Report {stamp}");
w.AppendLine(CultureInfo.InvariantCulture, $"CLI: {s.CliPath} | {s.CliVersion}");
w.AppendLine(CultureInfo.InvariantCulture, $"Oracle: {s.OraclePath} | {s.OracleVersion}");
w.AppendLine(CultureInfo.InvariantCulture,
$"xdvdfs: {(s.XdvdfsPath.Length > 0 ? s.XdvdfsPath : "(not found)")} | {s.XdvdfsVersion}");
w.AppendLine(CultureInfo.InvariantCulture,
$"xboxkit: {(s.XboxkitPath.Length > 0 ? s.XboxkitPath : "(not found)")} | {s.XboxkitVersion}");
w.AppendLine(CultureInfo.InvariantCulture,
$"Seed: {s.Seed} | Ops: {string.Join(", ", s.Ops)} | Work: {s.WorkRoot}");
w.AppendLine(CultureInfo.InvariantCulture, $"ISOs ({picked.Count}):");
foreach (string iso in picked)
{
w.AppendLine(CultureInfo.InvariantCulture, $" {iso}");
}
w.AppendLine(
CultureInfo.InvariantCulture,
$"Summary: {s.PassedSubs}/{s.TotalSubs} checks passed, {s.FailedSubs} failed, {s.SkippedSubs} skipped in {s.Elapsed.TotalSeconds:F1}s");
double cliTotal = s.IsoResults.SelectMany(static r => r.Subs).Sum(static x => x.CliSeconds);
double nativeTotal = s.IsoResults.SelectMany(static r => r.Subs).Sum(static x => x.OracleSeconds);
string timeLine = $"Time: cli {cliTotal:F1}s vs native {nativeTotal:F1}s" +
(nativeTotal > 0.05 ? $" (cli {cliTotal / nativeTotal:F2}x native)" : string.Empty);
w.AppendLine(timeLine);
w.AppendLine();
foreach (IsoResult f in s.IsoResults)
{
w.AppendLine(
CultureInfo.InvariantCulture,
$"{f.FileName} ({f.FileSize} bytes) - {(f.HasFailures ? "FAIL" : f.AllPassed ? "PASS" : "OK/SKIP")} {f.Seconds:F1}s");
foreach (SubResult sub in f.Subs)
{
w.AppendLine(
CultureInfo.InvariantCulture,
$" {sub.Op,-8} {sub.Status,-7} {sub.Seconds,8:F1}s (cli {sub.CliSeconds,7:F1}s / native {sub.OracleSeconds,7:F1}s) {sub.Detail.Replace('\n', ' ').Trim()}");
}
w.AppendLine();
}
return w.ToString();
}
private static string BuildJson(BattleSession s, IReadOnlyList<string> picked, string stamp) =>
JsonSerializer.Serialize(new
{
timestamp = stamp,
seed = s.Seed,
ops = s.Ops,
cli = new { path = s.CliPath, version = s.CliVersion },
oracle = new { path = s.OraclePath, version = s.OracleVersion },
xdvdfs = new { path = s.XdvdfsPath, version = s.XdvdfsVersion },
xboxkit = new { path = s.XboxkitPath, version = s.XboxkitVersion },
workRoot = s.WorkRoot,
totalIsos = s.TotalIsos,
failedIsos = s.FailedIsos,
totalChecks = s.TotalSubs,
passedChecks = s.PassedSubs,
failedChecks = s.FailedSubs,
skippedChecks = s.SkippedSubs,
elapsedSeconds = s.Elapsed.TotalSeconds,
cliSecondsTotal = s.IsoResults.SelectMany(static r => r.Subs).Sum(static x => x.CliSeconds),
nativeSecondsTotal = s.IsoResults.SelectMany(static r => r.Subs).Sum(static x => x.OracleSeconds),
isos = picked,
results = s.IsoResults.Select(f => new
{
f.FileName,
f.FilePath,
f.FileSize,
f.Seconds,
f.AllPassed,
subs = f.Subs.Select(sub => new
{
sub.Op,
status = sub.Status.ToString(),
sub.Detail,
sub.Seconds,
sub.CliSeconds,
sub.OracleSeconds,
}),
}),
}, new JsonSerializerOptions { WriteIndented = true });
}