213 lines
9.8 KiB
C#
213 lines
9.8 KiB
C#
using System.CommandLine;
|
|
using NatsNet.PortTracker.Data;
|
|
|
|
namespace NatsNet.PortTracker.Commands;
|
|
|
|
public static class PhaseCommands
|
|
{
|
|
private static readonly (int Number, string Name, string Description)[] Phases =
|
|
[
|
|
(1, "Analysis & Schema", "Run Go AST analyzer, populate DB schema, map libraries"),
|
|
(2, "Core Infrastructure", "Port foundational modules (logging, errors, options)"),
|
|
(3, "Message Layer", "Port message parsing, headers, protocol handling"),
|
|
(4, "Connection Layer", "Port connection management, reconnection logic"),
|
|
(5, "Client API", "Port publish, subscribe, request-reply"),
|
|
(6, "Advanced Features", "Port JetStream, KV, Object Store, Services"),
|
|
(7, "Testing & Verification", "Port and verify all unit tests, integration tests"),
|
|
];
|
|
|
|
public static Command Create(Option<string> dbOption, Option<string> schemaOption)
|
|
{
|
|
var phaseCommand = new Command("phase", "Manage porting phases");
|
|
|
|
// list
|
|
var listCmd = new Command("list", "List all phases with status");
|
|
listCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
using var db = new Database(dbPath);
|
|
|
|
Console.WriteLine($"{"Phase",-7} {"Name",-25} {"Description",-55} {"Status",-12}");
|
|
Console.WriteLine(new string('-', 99));
|
|
foreach (var (number, name, description) in Phases)
|
|
{
|
|
var status = CalculatePhaseStatus(db, number);
|
|
Console.WriteLine($"{number,-7} {name,-25} {description,-55} {status,-12}");
|
|
}
|
|
});
|
|
|
|
// check
|
|
var checkPhase = new Argument<int>("phase") { Description = "Phase number (1-7)" };
|
|
var checkCmd = new Command("check", "Check phase completion status");
|
|
checkCmd.Add(checkPhase);
|
|
checkCmd.SetAction(parseResult =>
|
|
{
|
|
var dbPath = parseResult.GetValue(dbOption)!;
|
|
var phase = parseResult.GetValue(checkPhase);
|
|
using var db = new Database(dbPath);
|
|
|
|
if (phase < 1 || phase > 7)
|
|
{
|
|
Console.WriteLine("Phase must be between 1 and 7.");
|
|
return;
|
|
}
|
|
|
|
var (_, name, description) = Phases[phase - 1];
|
|
Console.WriteLine($"Phase {phase}: {name}");
|
|
Console.WriteLine($" {description}\n");
|
|
|
|
RunPhaseCheck(db, phase);
|
|
});
|
|
|
|
phaseCommand.Add(listCmd);
|
|
phaseCommand.Add(checkCmd);
|
|
|
|
return phaseCommand;
|
|
}
|
|
|
|
private static string CalculatePhaseStatus(Database db, int phase)
|
|
{
|
|
return phase switch
|
|
{
|
|
1 => CalculatePhase1Status(db),
|
|
2 => CalculateModulePhaseStatus(db, "Core Infrastructure"),
|
|
3 => CalculateModulePhaseStatus(db, "Message Layer"),
|
|
4 => CalculateModulePhaseStatus(db, "Connection Layer"),
|
|
5 => CalculateModulePhaseStatus(db, "Client API"),
|
|
6 => CalculateModulePhaseStatus(db, "Advanced Features"),
|
|
7 => CalculatePhase7Status(db),
|
|
_ => "unknown"
|
|
};
|
|
}
|
|
|
|
private static string CalculatePhase1Status(Database db)
|
|
{
|
|
var totalModules = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules");
|
|
var totalLibraries = db.ExecuteScalar<long>("SELECT COUNT(*) FROM library_mappings");
|
|
if (totalModules == 0 && totalLibraries == 0) return "not_started";
|
|
var mappedLibraries = db.ExecuteScalar<long>("SELECT COUNT(*) FROM library_mappings WHERE status != 'not_mapped'");
|
|
if (totalModules > 0 && (totalLibraries == 0 || mappedLibraries == totalLibraries)) return "complete";
|
|
return "in_progress";
|
|
}
|
|
|
|
private static string CalculateModulePhaseStatus(Database db, string phaseDescription)
|
|
{
|
|
// Generic phase status based on overall module completion
|
|
var total = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules");
|
|
if (total == 0) return "not_started";
|
|
var done = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules WHERE status IN ('complete', 'verified', 'n_a')");
|
|
if (done == total) return "complete";
|
|
var started = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules WHERE status != 'not_started'");
|
|
return started > 0 ? "in_progress" : "not_started";
|
|
}
|
|
|
|
private static string CalculatePhase7Status(Database db)
|
|
{
|
|
var totalTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests");
|
|
if (totalTests == 0) return "not_started";
|
|
var doneTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests WHERE status IN ('complete', 'verified', 'n_a')");
|
|
if (doneTests == totalTests) return "complete";
|
|
var startedTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests WHERE status != 'not_started'");
|
|
return startedTests > 0 ? "in_progress" : "not_started";
|
|
}
|
|
|
|
private static void RunPhaseCheck(Database db, int phase)
|
|
{
|
|
switch (phase)
|
|
{
|
|
case 1:
|
|
CheckPhase1(db);
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
CheckModulePhase(db, phase);
|
|
break;
|
|
case 7:
|
|
CheckPhase7(db);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void CheckPhase1(Database db)
|
|
{
|
|
var totalModules = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules");
|
|
var totalFeatures = db.ExecuteScalar<long>("SELECT COUNT(*) FROM features");
|
|
var totalTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests");
|
|
var totalLibs = db.ExecuteScalar<long>("SELECT COUNT(*) FROM library_mappings");
|
|
var mappedLibs = db.ExecuteScalar<long>("SELECT COUNT(*) FROM library_mappings WHERE status != 'not_mapped'");
|
|
var totalDeps = db.ExecuteScalar<long>("SELECT COUNT(*) FROM dependencies");
|
|
|
|
Console.WriteLine("Phase 1 Checklist:");
|
|
Console.WriteLine($" [{ (totalModules > 0 ? "x" : " ") }] Modules populated: {totalModules}");
|
|
Console.WriteLine($" [{ (totalFeatures > 0 ? "x" : " ") }] Features populated: {totalFeatures}");
|
|
Console.WriteLine($" [{ (totalTests > 0 ? "x" : " ") }] Unit tests populated: {totalTests}");
|
|
Console.WriteLine($" [{ (totalDeps > 0 ? "x" : " ") }] Dependencies mapped: {totalDeps}");
|
|
Console.WriteLine($" [{ (totalLibs > 0 ? "x" : " ") }] Libraries identified: {totalLibs}");
|
|
Console.WriteLine($" [{ (totalLibs > 0 && mappedLibs == totalLibs ? "x" : " ") }] All libraries mapped: {mappedLibs}/{totalLibs}");
|
|
}
|
|
|
|
private static void CheckModulePhase(Database db, int phase)
|
|
{
|
|
var totalModules = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules");
|
|
var doneModules = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules WHERE status IN ('complete', 'verified', 'n_a')");
|
|
var stubModules = db.ExecuteScalar<long>("SELECT COUNT(*) FROM modules WHERE status = 'stub'");
|
|
var totalFeatures = db.ExecuteScalar<long>("SELECT COUNT(*) FROM features");
|
|
var doneFeatures = db.ExecuteScalar<long>("SELECT COUNT(*) FROM features WHERE status IN ('complete', 'verified', 'n_a')");
|
|
var stubFeatures = db.ExecuteScalar<long>("SELECT COUNT(*) FROM features WHERE status = 'stub'");
|
|
|
|
var modPct = totalModules > 0 ? (double)doneModules / totalModules * 100 : 0;
|
|
var featPct = totalFeatures > 0 ? (double)doneFeatures / totalFeatures * 100 : 0;
|
|
|
|
Console.WriteLine($"Phase {phase} Progress:");
|
|
Console.WriteLine($" Modules: {doneModules}/{totalModules} complete ({modPct:F1}%), {stubModules} stubs");
|
|
Console.WriteLine($" Features: {doneFeatures}/{totalFeatures} complete ({featPct:F1}%), {stubFeatures} stubs");
|
|
|
|
// Show incomplete modules
|
|
var incomplete = db.Query(
|
|
"SELECT id, name, status FROM modules WHERE status NOT IN ('complete', 'verified', 'n_a') ORDER BY name");
|
|
if (incomplete.Count > 0)
|
|
{
|
|
Console.WriteLine($"\n Incomplete modules ({incomplete.Count}):");
|
|
foreach (var m in incomplete)
|
|
Console.WriteLine($" #{m["id"],-5} {m["name"],-30} {m["status"]}");
|
|
}
|
|
}
|
|
|
|
private static void CheckPhase7(Database db)
|
|
{
|
|
var totalTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests");
|
|
var doneTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests WHERE status IN ('complete', 'verified', 'n_a')");
|
|
var stubTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests WHERE status = 'stub'");
|
|
var verifiedTests = db.ExecuteScalar<long>("SELECT COUNT(*) FROM unit_tests WHERE status = 'verified'");
|
|
|
|
var pct = totalTests > 0 ? (double)doneTests / totalTests * 100 : 0;
|
|
|
|
Console.WriteLine("Phase 7 Progress:");
|
|
Console.WriteLine($" Total tests: {totalTests}");
|
|
Console.WriteLine($" Complete: {doneTests - verifiedTests}");
|
|
Console.WriteLine($" Verified: {verifiedTests}");
|
|
Console.WriteLine($" Stubs: {stubTests}");
|
|
Console.WriteLine($" Not started: {totalTests - doneTests - stubTests}");
|
|
Console.WriteLine($" Progress: {pct:F1}%");
|
|
|
|
// Modules with incomplete tests
|
|
var modulesWithIncomplete = db.Query(@"
|
|
SELECT m.id, m.name, COUNT(*) as total,
|
|
SUM(CASE WHEN t.status IN ('complete', 'verified', 'n_a') THEN 1 ELSE 0 END) as done
|
|
FROM unit_tests t
|
|
JOIN modules m ON t.module_id = m.id
|
|
GROUP BY m.id, m.name
|
|
HAVING done < total
|
|
ORDER BY m.name");
|
|
if (modulesWithIncomplete.Count > 0)
|
|
{
|
|
Console.WriteLine($"\n Modules with incomplete tests ({modulesWithIncomplete.Count}):");
|
|
foreach (var m in modulesWithIncomplete)
|
|
Console.WriteLine($" #{m["id"],-5} {m["name"],-30} {m["done"]}/{m["total"]}");
|
|
}
|
|
}
|
|
}
|