From 387e00f160d41e4575a1e1944c7ea2c02bfcd7b5 Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Mon, 24 Feb 2025 21:16:56 -0600 Subject: [PATCH] Upload patchfiles to azure blobstore --- .gitignore | 1 + ALttPRandomizer/ALttPRandomizer.csproj | 2 + ALttPRandomizer/Options/ServiceOptions.cs | 7 ++ ALttPRandomizer/Program.cs | 13 ++++ ALttPRandomizer/Randomizer.cs | 69 +++++++++++++++++--- ALttPRandomizer/appsettings.Development.json | 6 -- 6 files changed, 83 insertions(+), 15 deletions(-) delete mode 100644 ALttPRandomizer/appsettings.Development.json diff --git a/.gitignore b/.gitignore index 1ed5820..8700415 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.sfc +appsettings.Development.json ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. diff --git a/ALttPRandomizer/ALttPRandomizer.csproj b/ALttPRandomizer/ALttPRandomizer.csproj index 66ee819..d063360 100644 --- a/ALttPRandomizer/ALttPRandomizer.csproj +++ b/ALttPRandomizer/ALttPRandomizer.csproj @@ -9,6 +9,8 @@ + + diff --git a/ALttPRandomizer/Options/ServiceOptions.cs b/ALttPRandomizer/Options/ServiceOptions.cs index 32ff7e7..4e8582a 100644 --- a/ALttPRandomizer/Options/ServiceOptions.cs +++ b/ALttPRandomizer/Options/ServiceOptions.cs @@ -1,6 +1,13 @@ namespace ALttPRandomizer.Options { + using System; + public class ServiceOptions { public string PythonPath { get; set; } = null!; public string RandomizerPath { get; set; } = null!; + public AzureSettings AzureSettings { get; set; } = new AzureSettings(); + } + + public class AzureSettings { + public Uri BlobstoreEndpoint { get; set; } = null!; } } diff --git a/ALttPRandomizer/Program.cs b/ALttPRandomizer/Program.cs index 1eeaae3..fb702be 100644 --- a/ALttPRandomizer/Program.cs +++ b/ALttPRandomizer/Program.cs @@ -2,9 +2,13 @@ { using System.Text.Json.Serialization; using ALttPRandomizer.Options; + using Azure.Identity; + using Azure.Storage.Blobs; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; internal class Program { @@ -19,10 +23,19 @@ builder.Services.Configure(builder.Configuration.GetSection("ALttPRandomizer")); + builder.Services.AddLogging(lb => lb.AddConsole()); + builder.Services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())); builder.Services.AddSwaggerGen(); + var provider = builder.Services.BuildServiceProvider(); + var settings = provider.GetRequiredService>().CurrentValue!; + + var token = new DefaultAzureCredential(); + var seedClient = new BlobContainerClient(settings.AzureSettings.BlobstoreEndpoint, token); + + builder.Services.AddSingleton(seedClient); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/ALttPRandomizer/Randomizer.cs b/ALttPRandomizer/Randomizer.cs index f09260a..2ab5b30 100644 --- a/ALttPRandomizer/Randomizer.cs +++ b/ALttPRandomizer/Randomizer.cs @@ -1,53 +1,104 @@ namespace ALttPRandomizer { using ALttPRandomizer.Options; + using Azure.Storage.Blobs; + using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; + using System; using System.Diagnostics; + using System.IO; + using System.Threading.Tasks; public class Randomizer { - public Randomizer(IdGenerator idGenerator, IOptionsMonitor optionsMonitor) { + public Randomizer( + IdGenerator idGenerator, + BlobContainerClient seedClient, + IOptionsMonitor optionsMonitor, + ILogger logger) { this.IdGenerator = idGenerator; - this.optionsMonitor = optionsMonitor; + this.SeedClient = seedClient; + this.OptionsMonitor = optionsMonitor; + this.Logger = logger; } - private IOptionsMonitor optionsMonitor; - private IdGenerator IdGenerator; - private ServiceOptions Configuration => optionsMonitor.CurrentValue; + private BlobContainerClient SeedClient { get; } + private IOptionsMonitor OptionsMonitor { get; } + private IdGenerator IdGenerator { get; } + private ILogger Logger { get; } + private ServiceOptions Configuration => this.OptionsMonitor.CurrentValue; public string Randomize() { var start = new ProcessStartInfo() { FileName = Configuration.PythonPath, WorkingDirectory = Configuration.RandomizerPath, RedirectStandardOutput = true, + RedirectStandardError = true, }; + var id = IdGenerator.GenerateId(); + var args = start.ArgumentList; args.Add("DungeonRandomizer.py"); args.Add("--rom=../alttp.sfc"); args.Add("--bps"); + args.Add("--outputpath"); + args.Add(Path.GetTempPath()); + + args.Add("--outputname"); + args.Add(id); + args.Add("--quickswap"); var process = Process.Start(start) ?? throw new GenerationFailedException("Process failed to start."); process.EnableRaisingEvents = true; - var id = IdGenerator.GenerateId(); + process.OutputDataReceived += (_, args) => this.Logger.LogInformation("Randomizer STDOUT: {output}", args.Data); + process.ErrorDataReceived += (_, args) => this.Logger.LogInformation("Randomizer STDERR: {output}", args.Data); - process.Exited += (sender, args) => { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + process.Exited += async (sender, args) => { var exitcode = process.ExitCode; process.Dispose(); if (exitcode != 0) { this.GenerationFailed(id, exitcode); } else { - this.GenerationSucceeded(id); + await this.GenerationSucceeded(id); } }; return id; } - private void GenerationSucceeded(string id) { + private async Task GenerationSucceeded(string id) { + var rom = Path.Join(Path.GetTempPath(), string.Format("DR_{0}.sfc", id)); + var bpsIn = Path.Join(Path.GetTempPath(), string.Format("DR_{0}.bps", id)); + var bpsOut = string.Format("{0}/patch.bps", id); + + var spoilerIn = Path.Join(Path.GetTempPath(), string.Format("DR_{0}_Spoiler.txt", id)); + var spoilerOut = string.Format("{0}/spoiler.txt", id); + + var uploadPatch = UploadFile(bpsOut, bpsIn); + var uploadSpoiler = UploadFile(spoilerOut, spoilerIn); + + await Task.WhenAll(uploadPatch, uploadSpoiler); + + File.Delete(rom); + + this.Logger.LogDebug("Finished uploading seed id {id}", id); + } + + private async Task UploadFile(string name, string filepath) { + using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read)) { + this.Logger.LogDebug("Uploading file {filepath} -> {name}", filepath, name); + await this.SeedClient.UploadBlobAsync(name, stream); + } + + this.Logger.LogDebug("Deleting file {filepath}", filepath); + File.Delete(filepath); } private void GenerationFailed(string id, int exitcode) { diff --git a/ALttPRandomizer/appsettings.Development.json b/ALttPRandomizer/appsettings.Development.json deleted file mode 100644 index f6af898..0000000 --- a/ALttPRandomizer/appsettings.Development.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ALttPRandomizer": { - "pythonPath": "C:\\Program Files (x86)\\Python38-32\\python", - "randomizerPath": "C:\\Users\\ardna\\git-projects\\ALttPRandomizer\\ALttPDoorRandomizer" - } -} \ No newline at end of file