-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
163 lines (139 loc) · 5.82 KB
/
Program.cs
File metadata and controls
163 lines (139 loc) · 5.82 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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MySupplyChain.Launcher;
class Program
{
// Relative paths from solution root
private const string ModelTrainerProject = "MySupplyChain.ModelTrainer/MySupplyChain.ModelTrainer.csproj";
private const string ApiProject = "MySupplyChain.API/MySupplyChain.API.csproj";
private const string ModelsDirectory = "MySupplyChain.Infrastructure/MLModels";
private const string RequiredModelFile = "sales_model.zip";
static async Task<int> Main(string[] args)
{
var solutionRoot = FindSolutionRoot();
if (solutionRoot is null)
{
PrintError(
"Could not locate solution root (.slnx / .sln file). Run this from inside the MySupplyChain folder.");
return 1;
}
PrintBanner();
// ── Step 1: Train ML model if it doesn't exist ───────────────────────
var modelPath = Path.Combine(solutionRoot, ModelsDirectory, RequiredModelFile);
if (!File.Exists(modelPath))
{
PrintStep(1, "ML model not found. Running ModelTrainer first...");
var trainerResult = await RunProjectAsync(solutionRoot, ModelTrainerProject, args);
if (trainerResult != 0)
{
PrintError("ModelTrainer failed. Fix the trainer errors above, then try again.");
return trainerResult;
}
PrintSuccess("ML model trained and saved.");
}
else
{
PrintStep(1, $"ML model found ({RequiredModelFile}). Skipping training.");
}
// ── Step 2: Start the API ─────────────────────────────────────────────
PrintStep(2, "Starting MySupplyChain API...");
Console.WriteLine();
return await RunProjectAsync(solutionRoot, ApiProject, args, attach: true);
}
// ── Helpers ───────────────────────────────────────────────────────────────
/// <summary>
/// Runs a dotnet project and returns its exit code.
/// When <paramref name="attach"/> is true the child process inherits this
/// console so Ctrl+C / Ctrl+Break propagate naturally.
/// </summary>
static async Task<int> RunProjectAsync(
string workingDir,
string projectRelativePath,
string[] extraArgs,
bool attach = false)
{
var dotnet = GetDotnetExecutable();
var projectFull = Path.Combine(workingDir, projectRelativePath);
// Forward any extra args the user passed (e.g. --urls, --environment)
var argString = $"run --project \"{projectFull}\"";
if (extraArgs.Length > 0)
argString += " -- " + string.Join(" ", extraArgs);
var psi = new ProcessStartInfo
{
FileName = dotnet,
Arguments = argString,
WorkingDirectory = workingDir,
UseShellExecute = false,
RedirectStandardOutput = !attach,
RedirectStandardError = !attach,
CreateNoWindow = false,
};
using var process = new Process();
process.StartInfo = psi;
process.EnableRaisingEvents = true;
if (!attach)
{
// Capture and relay output for ModelTrainer
process.OutputDataReceived += (_, e) =>
{
if (e.Data != null) Console.WriteLine(e.Data);
};
process.ErrorDataReceived += (_, e) =>
{
if (e.Data != null) PrintError(e.Data);
};
}
process.Start();
if (!attach)
{
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
await process.WaitForExitAsync();
return process.ExitCode;
}
static string? FindSolutionRoot()
{
var dir = new DirectoryInfo(AppContext.BaseDirectory);
while (dir != null)
{
if (dir.GetFiles("*.slnx").Length > 0 || dir.GetFiles("*.sln").Length > 0)
return dir.FullName;
dir = dir.Parent;
}
return null;
}
static string GetDotnetExecutable() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dotnet.exe" : "dotnet";
// ── Console formatting ────────────────────────────────────────────────────
static void PrintBanner()
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine();
Console.WriteLine(" ╔══════════════════════════════════════════╗");
Console.WriteLine(" ║ 🚛 MySupplyChain — Smart Launcher ║");
Console.WriteLine(" ╚══════════════════════════════════════════╝");
Console.ResetColor();
Console.WriteLine();
}
static void PrintStep(int step, string message)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write($" [{step}] ");
Console.ResetColor();
Console.WriteLine(message);
}
static void PrintSuccess(string message)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($" ✓ {message}");
Console.ResetColor();
Console.WriteLine();
}
static void PrintError(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($" ✗ {message}");
Console.ResetColor();
}
}