Add craftingway macro support
This commit is contained in:
@@ -8,10 +8,10 @@ using System.Diagnostics;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
|
||||||
|
|
||||||
namespace Craftimizer.Utils;
|
namespace Craftimizer.Utils;
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ public static class MacroImport
|
|||||||
public static IReadOnlyList<ActionType>? TryParseMacro(string inputMacro)
|
public static IReadOnlyList<ActionType>? TryParseMacro(string inputMacro)
|
||||||
{
|
{
|
||||||
var actions = new List<ActionType>();
|
var actions = new List<ActionType>();
|
||||||
foreach(var line in inputMacro.ReplaceLineEndings("\n").Split("\n"))
|
foreach (var line in inputMacro.ReplaceLineEndings("\n").Split("\n"))
|
||||||
{
|
{
|
||||||
if (TryParseLine(line) is { } action)
|
if (TryParseLine(line) is { } action)
|
||||||
actions.Add(action);
|
actions.Add(action);
|
||||||
@@ -55,7 +55,7 @@ public static class MacroImport
|
|||||||
line = line[..end];
|
line = line[..end];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var action in Enum.GetValues<ActionType>())
|
foreach (var action in Enum.GetValues<ActionType>())
|
||||||
{
|
{
|
||||||
if (line.Equals(action.GetName(ClassJob.Carpenter), StringComparison.OrdinalIgnoreCase))
|
if (line.Equals(action.GetName(ClassJob.Carpenter), StringComparison.OrdinalIgnoreCase))
|
||||||
return action;
|
return action;
|
||||||
@@ -173,6 +173,29 @@ public static class MacroImport
|
|||||||
public ErrorData? Error { get; set; }
|
public ErrorData? Error { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed record CraftingwayMacro
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Slug { get; set; }
|
||||||
|
public string? Version { get; set; }
|
||||||
|
public string? Job { get; set; }
|
||||||
|
[JsonPropertyName("job_level")]
|
||||||
|
public int JobLevel { get; set; }
|
||||||
|
public int Craftsmanship { get; set; }
|
||||||
|
public int Control { get; set; }
|
||||||
|
public int CP { get; set; }
|
||||||
|
public string? Food { get; set; }
|
||||||
|
public string? Potion { get; set; }
|
||||||
|
[JsonPropertyName("recipe_job_level")]
|
||||||
|
public int RecipeJobLevel { get; set; }
|
||||||
|
public string? Recipe { get; set; }
|
||||||
|
// HqIngredients
|
||||||
|
public string? Actions { get; set; }
|
||||||
|
[JsonPropertyName("created_at")]
|
||||||
|
public long CreatedAt { get; set; }
|
||||||
|
public string? Error { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public readonly record struct RetrievedMacro(string Name, IReadOnlyList<ActionType> Actions);
|
public readonly record struct RetrievedMacro(string Name, IReadOnlyList<ActionType> Actions);
|
||||||
|
|
||||||
private static async Task<RetrievedMacro> RetrieveTeamcraftUrl(Uri uri, CancellationToken token)
|
private static async Task<RetrievedMacro> RetrieveTeamcraftUrl(Uri uri, CancellationToken token)
|
||||||
@@ -195,7 +218,10 @@ public static class MacroImport
|
|||||||
|
|
||||||
var id = path[(lastSlash + 1)..];
|
var id = path[(lastSlash + 1)..];
|
||||||
|
|
||||||
var resp = await client.GetFromJsonAsync<TeamcraftMacro>($"https://firestore.googleapis.com/v1beta1/projects/ffxivteamcraft/databases/(default)/documents/rotations/{id}", token).ConfigureAwait(false);
|
var resp = await client.GetFromJsonAsync<TeamcraftMacro>(
|
||||||
|
$"https://firestore.googleapis.com/v1beta1/projects/ffxivteamcraft/databases/(default)/documents/rotations/{id}",
|
||||||
|
token).
|
||||||
|
ConfigureAwait(false);
|
||||||
if (resp is null)
|
if (resp is null)
|
||||||
throw new Exception("Internal error; failed to retrieve macro");
|
throw new Exception("Internal error; failed to retrieve macro");
|
||||||
if (resp.Error is { } error)
|
if (resp.Error is { } error)
|
||||||
@@ -208,7 +234,7 @@ public static class MacroImport
|
|||||||
$"rlvl{recipe.RLvl.Value} - {rotation.Rotation.Value.Length} steps, {recipe.Durability.Value} dur" :
|
$"rlvl{recipe.RLvl.Value} - {rotation.Rotation.Value.Length} steps, {recipe.Durability.Value} dur" :
|
||||||
"New Teamcraft Rotation");
|
"New Teamcraft Rotation");
|
||||||
var actions = new List<ActionType>();
|
var actions = new List<ActionType>();
|
||||||
foreach(var action in rotation.Rotation.Value)
|
foreach (var action in rotation.Rotation.Value)
|
||||||
{
|
{
|
||||||
ActionType? actionType = action.Value switch
|
ActionType? actionType = action.Value switch
|
||||||
{
|
{
|
||||||
@@ -264,6 +290,69 @@ public static class MacroImport
|
|||||||
ConnectCallback = heCallback.ConnectCallback,
|
ConnectCallback = heCallback.ConnectCallback,
|
||||||
});
|
});
|
||||||
|
|
||||||
throw new NotImplementedException();
|
// https://craftingway.app/rotation/variable-blueprint-KmrvS
|
||||||
|
|
||||||
|
var path = uri.GetComponents(UriComponents.Path, UriFormat.SafeUnescaped);
|
||||||
|
if (!path.StartsWith("rotation/", StringComparison.Ordinal))
|
||||||
|
throw new ArgumentException("Craftingway macro url should start with /rotation", nameof(uri));
|
||||||
|
path = path[9..];
|
||||||
|
|
||||||
|
var lastSlash = path.LastIndexOf('/');
|
||||||
|
if (lastSlash != -1)
|
||||||
|
throw new ArgumentException("Craftingway macro url is not in the right format", nameof(uri));
|
||||||
|
|
||||||
|
var id = path;
|
||||||
|
|
||||||
|
var resp = await client.GetFromJsonAsync<CraftingwayMacro>(
|
||||||
|
$"https://servingway.fly.dev/rotation/{id}",
|
||||||
|
token)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
if (resp is null)
|
||||||
|
throw new Exception("Internal error; failed to retrieve macro");
|
||||||
|
if (resp.Error is { } error)
|
||||||
|
throw new Exception($"Internal server error; {error}");
|
||||||
|
if (resp.Actions is not { } rotation)
|
||||||
|
throw new Exception($"Internal error; No actions or error was returned");
|
||||||
|
// https://github.com/ffxiv-teamcraft/ffxiv-teamcraft/blob/67f453041c6b2b31d32fcf6e1fd53aa38ed7a12b/apps/client/src/app/model/other/crafting-rotation.ts#L49
|
||||||
|
var name = resp.Slug ?? "New Craftinway Rotation";
|
||||||
|
var actions = new List<ActionType>();
|
||||||
|
foreach (var action in resp.Actions.Split(','))
|
||||||
|
{
|
||||||
|
ActionType? actionType = action switch
|
||||||
|
{
|
||||||
|
"BasicSynthesis" => ActionType.BasicSynthesis,
|
||||||
|
"BasicTouch" => ActionType.BasicTouch,
|
||||||
|
"MastersMend" => ActionType.MastersMend,
|
||||||
|
"Observe" => ActionType.Observe,
|
||||||
|
"WasteNot" => ActionType.WasteNot,
|
||||||
|
"Veneration" => ActionType.Veneration,
|
||||||
|
"StandardTouch" => ActionType.StandardTouch,
|
||||||
|
"GreatStrides" => ActionType.GreatStrides,
|
||||||
|
"Innovation" => ActionType.Innovation,
|
||||||
|
"BasicSynthesisTraited" => ActionType.BasicSynthesis,
|
||||||
|
"WasteNotII" => ActionType.WasteNot2,
|
||||||
|
"ByregotsBlessing" => ActionType.ByregotsBlessing,
|
||||||
|
"MuscleMemory" => ActionType.MuscleMemory,
|
||||||
|
"CarefulSynthesis" => ActionType.CarefulSynthesis,
|
||||||
|
"Manipulation" => ActionType.Manipulation,
|
||||||
|
"PrudentTouch" => ActionType.PrudentTouch,
|
||||||
|
"FocusedSynthesis" => ActionType.FocusedSynthesis,
|
||||||
|
"FocusedTouch" => ActionType.FocusedTouch,
|
||||||
|
"Reflect" => ActionType.Reflect,
|
||||||
|
"PreparatoryTouch" => ActionType.PreparatoryTouch,
|
||||||
|
"Groundwork" => ActionType.Groundwork,
|
||||||
|
"DelicateSynthesis" => ActionType.DelicateSynthesis,
|
||||||
|
"TrainedEye" => ActionType.TrainedEye,
|
||||||
|
"CarefulSynthesisTraited" => ActionType.CarefulSynthesis,
|
||||||
|
"AdvancedTouch" => ActionType.AdvancedTouch,
|
||||||
|
"GroundworkTraited" => ActionType.Groundwork,
|
||||||
|
"PrudentSynthesis" => ActionType.PrudentSynthesis,
|
||||||
|
"TrainedFinesse" => ActionType.TrainedFinesse,
|
||||||
|
{ } actionValue => throw new Exception($"Unknown action {actionValue}"),
|
||||||
|
};
|
||||||
|
if (actionType.HasValue)
|
||||||
|
actions.Add(actionType.Value);
|
||||||
|
}
|
||||||
|
return new(name, actions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user