2026-06-05 13:44:39 +09:00

176 lines
6.9 KiB
C#

using Aurora;
using Aurora.Api;
using Hermes;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace VisionCommon {
/// <summary>
/// 현재 실행 중인 SW의 Recipe 구성에 맞게
/// 장비에 저장된 Recipe 파일을 업데이트 한다.
/// </summary>
public static class RecipeUpdater {
private const string KEY_UNIT_RECIPES = nameof(VisionDef.UnitRecipes);
private const string KEY_SUB_SYS_RECIPES = nameof(UnitRecipe.SubSysRecipes);
private const string KEY_FOV_RECIPES = nameof(SubSysRecipe.FovRecipes);
private const string KEY_ALIGN_RECIPES = nameof(SubSysRecipe.AlignRecipes);
private static Logger _logger = new Logger(nameof(RecipeUpdater));
/// <summary>
/// 레시피 업데이트를 실행한다.
/// </summary>
/// <param name="recipeModelType">레시피 또는 모델</param>
/// <returns>실행 결과</returns>
public static int Run(eRecipeModelType recipeModelType) {
var recipeDirectories = RecipeUpdaterUtil.GetDataDirectories(recipeModelType);
var updaters = GetRecipeUpdaters();
foreach (var recipeDir in recipeDirectories) {
var recipeFilePath = Path.Combine(recipeDir, $"{VisionKeys.VisionRecipeKey}.json");
if (File.Exists(recipeFilePath)) {
JToken machineRecipeOriginal = JsonManager.ParseFromFile(recipeFilePath);
if (machineRecipeOriginal == null) {
_logger.E($"Read recipe file error : {recipeFilePath}");
continue;
}
JToken machineRecipe = machineRecipeOriginal.DeepClone();
SetInitialVersion(machineRecipe);
var machineRecipeVersion = GetRecipeVersion(machineRecipe);
if (!IsUpdatable(machineRecipeVersion)) {
continue;
}
var result = Update(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters);
if (result == E1.OK) {
SaveBackupFile(machineRecipeOriginal, machineRecipeVersion, recipeDir);
SaveUpdateFile(machineRecipe, recipeDir);
}
}
}
return E1.OK;
}
private static List<Updater> GetRecipeUpdaters() {
var updaters = new List<Updater>();
Type targetType = typeof(Updater);
Assembly assembly = Assembly.GetExecutingAssembly();
var types = assembly.GetTypes();
foreach (var type in types) {
if (targetType.IsAssignableFrom(type)) {
ConstructorInfo ctor = type.GetConstructor(new Type[] { });
if (ctor != null) {
updaters.Add((Updater)ctor.Invoke(new object[] { }));
}
}
}
return updaters;
}
private static void SetInitialVersion(JToken machineRecipe) {
var machineRecipeVersion = GetRecipeVersion(machineRecipe);
if (machineRecipeVersion == 0) {
SetRecipeVersion(machineRecipe, VisionDef.RECIPE_VERSION_INITIAL);
}
}
private static bool IsUpdatable(double machineRecipeVersion) {
return !MathUtil.Equals(machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, 0.01);
}
private static double GetRecipeVersion(JToken machineRecipe) {
try {
var versionToken = machineRecipe.SelectToken(nameof(VisionDef.Version));
if (versionToken != null) {
return Math.Round(versionToken.ToObject<double>(), 1);
}
}
catch (Exception e) {
_logger.E(e.Message);
}
return 0;
}
private static int SetRecipeVersion(JToken machineRecipe, double version) {
try {
var versionToken = machineRecipe.SelectToken(nameof(VisionDef.Version));
if (versionToken == null) {
machineRecipe[nameof(VisionDef.Version)] = version;
}
else {
versionToken.Replace(new JValue(Math.Round(version, 1)));
}
}
catch (Exception e) {
_logger.E(e.Message);
return E1.GENERIC;
}
return E1.OK;
}
private static int Update(JToken machineRecipe, double machineRecipeVersion, double swVersion, List<Updater> updaters) {
if (machineRecipeVersion < VisionDef.RECIPE_VERSION_CURRENT) {
return Upgrade(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters);
}
else if (VisionDef.RECIPE_VERSION_CURRENT < machineRecipeVersion) {
return Downgrade(machineRecipe, machineRecipeVersion, VisionDef.RECIPE_VERSION_CURRENT, updaters);
}
return E1.GENERIC;
}
private static int Upgrade(JToken machineRecipe, double machineRecipeVersion, double swVersion, List<Updater> updaters) {
for (double curVer = machineRecipeVersion; curVer < swVersion; curVer += 0.1) {
double nextVer = curVer + 0.1;
foreach (var updater in updaters) {
updater.Update(machineRecipe, curVer, nextVer);
}
SetRecipeVersion(machineRecipe, nextVer);
}
return E1.OK;
}
private static int Downgrade(JToken machineRecipe, double machineRecipeVersion, double swVersion, List<Updater> updaters) {
for (double curVer = machineRecipeVersion; swVersion < curVer; curVer -= 0.1) {
double nextVer = curVer - 0.1;
foreach (var updater in updaters) {
updater.Update(machineRecipe, curVer, nextVer);
}
SetRecipeVersion(machineRecipe, nextVer);
}
return E1.OK;
}
private static int SaveBackupFile(
JToken machineRecipeOriginal, double machineRecipeVersion, string recipeDir) {
string datetimeStr = DateTime.Now.ToString("yyyyMMdd_hhmmss");
string backupFileName = $"{VisionKeys.VisionRecipeKey}_{datetimeStr}_v{machineRecipeVersion}.json";
return JsonManager.SaveToFile(
machineRecipeOriginal,
Path.Combine(recipeDir, backupFileName));
}
private static int SaveUpdateFile(JToken machineRecipe, string recipeDir) {
return JsonManager.SaveToFile(
machineRecipe,
Path.Combine(recipeDir, $"{VisionKeys.VisionRecipeKey}.json"));
}
}
}