using System.Text.Json;
using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Localization;
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Outfitting;
using XFEEDToolBox.Core.Planning;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Galaxy;
namespace XFEEDToolBox.Test;
[TestFixture]
public class LocalizationPlanningTests
{
[Test] public void EveryPublishedModuleBlueprintShipAndEngineerHasIndependentChineseName()
{
var values=OutfittingCatalog.Default.Modules.Select(m=>m.Name).Concat(OutfittingCatalog.Default.ShipNames.Values).Concat(EngineeringCatalog.Default.Recipes.SelectMany(r=>r.Engineers.Append(r.Name).Append(r.Type)));
var missing=values.Distinct().Where(n=>ChineseNames.Translate(n)=="未收录名称").ToArray();
Check.That(missing.Length==0,"Missing: "+string.Join(", ",missing));
}
[Test] public void JournalNamesRenderChineseAndCanonicalEnglishWithoutChangingIdentity()
{
var module=new FittedModule{Slot="HugeHardpoint1",Item="hpt_multicannon_gimbal_huge",Name="多管机炮",Engineering=new(){Blueprint="Weapon_Overcharged",Level=3,ExperimentalEffect="special_auto_loader"}};
Check.That(module.DisplayName.Contains("多管机炮")&&module.OriginalName.Contains("Multi-Cannon"));
Check.Equal("超大型武器挂点 1",module.SlotName);Check.That(module.EngineeringText.Contains("超载")&&module.EngineeringText.Contains("自动装填"));
Check.That(module.EngineeringOriginal.Contains("Overcharged")&&module.EngineeringOriginal.Contains("Auto"));Check.Equal("Weapon_Overcharged",module.Engineering.Blueprint);
Check.Equal("hpt_multicannon_gimbal_huge",module.Item);
var localized=module with{Engineering=module.Engineering with{ExperimentalEffect="自动装填机构",ExperimentalEffectId="special_auto_loader"}};
Check.That(localized.EngineeringOriginal.Contains("Auto",StringComparison.OrdinalIgnoreCase)&&!ChineseNames.IsChinese(localized.EngineeringOriginal));
Check.Equal("军用内部槽位 01",ChineseNames.Slot("Military01"));
Check.Equal("货舱舱门",ChineseNames.Module("modularcargobaydoor"));Check.Equal("巨蟒座舱",ChineseNames.Module("anaconda_cockpit"));
Check.Equal("伤害类型: 热能",new EngineeringModifier("DamageType",null,null,false,"$Thermic;").Display);
}
[Test] public void GlobalListSharesEngineerProgressAndSubtractsInventoryOnce()
{
var module=new FittedModule{Item="hpt_multicannon_gimbal_large"};var target=new RefitTarget("Overcharged Weapon",5,1,"",1,false,true);
var access=new EngineerAccess{Id=1,Name="Tod McQuinn",Progress="Unlocked",Rank=4,ReputationMin=94.6,ReputationMax=94.6};
var p=new PlayerState{Engineers=[access],Materials=[new("nickel","Nickel",4,0,"Raw")],Credits=100,CreditsReliable=true};
var list=new[]{new UpgradeListEntry(Guid.NewGuid(),module,target,2,Purchase:true,UnitPrice:75),new UpgradeListEntry(Guid.NewGuid(),module,target,1,Purchase:true)};
var budget=UpgradeListPlanner.Calculate(list,p,EngineeringCatalog.Default);
Check.Equal(3,budget.Engineering.Modules.Count);Check.Equal(150m,budget.KnownCredits);Check.Equal(50m,budget.MissingCredits!.Value);Check.Equal(1,budget.UnquotedItems);
var nickel=budget.Engineering.Materials.Single(m=>m.Key=="nickel");Check.Equal(4,nickel.Owned);Check.Equal(Math.Max(0,nickel.Required-4),nickel.Missing);
Check.That(budget.Engineering.Modules[0].Rolls>budget.Engineering.Modules[1].Rolls);
}
[Test] public void GlobalListRefusesDuplicateOwnedModulesAndStaleConfiguration()
{
var module=new FittedModule{Slot="LargeHardpoint1",Item="hpt_multicannon_gimbal_large"};var t=new RefitTarget("Overcharged Weapon",5,1,"",1,false,true);
var entry=new UpgradeListEntry(Guid.NewGuid(),module,t,1,"ship:7:LargeHardpoint1");
var p=new PlayerState{Ships=[new(){ShipId=7,ConfigurationChanged=true,Modules=[module]}]};
Check.Throws<InvalidOperationException>(()=>UpgradeListPlanner.Calculate([entry],p,EngineeringCatalog.Default));
Check.Throws<InvalidOperationException>(()=>UpgradeListPlanner.Calculate([entry with{Quantity=2}],p,EngineeringCatalog.Default));
}
[Test] public void GalaxyDirectoryUsesMeasuredCoordinatesAndPreservesInt64Address()
{
using var json=JsonDocument.Parse("""[{"name":"Sol","id64":9007199254740993,"coords":{"x":0,"y":0,"z":0}},{"name":"Missing coords"}]""");
var systems=GalaxyCatalog.Parse(json.RootElement);Check.Equal(1,systems.Count);Check.Equal(9007199254740993L,systems[0].SystemAddress!.Value);Check.Equal(0d,systems[0].Position.DistanceTo(new(0,0,0)));
}
[Test] public void ModuleReferencePricesKeepMissingAndConflictingPricesUnknown()
{
Check.Equal(633199m,ModulePrices.Find("int_hyperdrive_size7_class1")!.Value);
Check.That(ModulePrices.Find("int_fueltank_size3_class3") is null&&ModulePrices.Find("unknown_future_module") is null);
}
}
using System.Text.Json;
using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Localization;
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Outfitting;
using XFEEDToolBox.Core.Planning;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Galaxy;
namespace XFEEDToolBox.Test;
[TestFixture]
public class LocalizationPlanningTests
{
[Test] public void EveryPublishedModuleBlueprintShipAndEngineerHasIndependentChineseName()
{
var values=OutfittingCatalog.Default.Modules.Select(m=>m.Name).Concat(OutfittingCatalog.Default.ShipNames.Values).Concat(EngineeringCatalog.Default.Recipes.SelectMany(r=>r.Engineers.Append(r.Name).Append(r.Type)));
var missing=values.Distinct().Where(n=>ChineseNames.Translate(n)=="未收录名称").ToArray();
Check.That(missing.Length==0,"Missing: "+string.Join(", ",missing));
}
[Test] public void JournalNamesRenderChineseAndCanonicalEnglishWithoutChangingIdentity()
{
var module=new FittedModule{Slot="HugeHardpoint1",Item="hpt_multicannon_gimbal_huge",Name="多管机炮",Engineering=new(){Blueprint="Weapon_Overcharged",Level=3,ExperimentalEffect="special_auto_loader"}};
Check.That(module.DisplayName.Contains("多管机炮")&&module.OriginalName.Contains("Multi-Cannon"));
Check.Equal("超大型武器挂点 1",module.SlotName);Check.That(module.EngineeringText.Contains("超载")&&module.EngineeringText.Contains("自动装填"));
Check.That(module.EngineeringOriginal.Contains("Overcharged")&&module.EngineeringOriginal.Contains("Auto"));Check.Equal("Weapon_Overcharged",module.Engineering.Blueprint);
Check.Equal("hpt_multicannon_gimbal_huge",module.Item);
var localized=module with{Engineering=module.Engineering with{ExperimentalEffect="自动装填机构",ExperimentalEffectId="special_auto_loader"}};
Check.That(localized.EngineeringOriginal.Contains("Auto",StringComparison.OrdinalIgnoreCase)&&!ChineseNames.IsChinese(localized.EngineeringOriginal));
Check.Equal("军用内部槽位 01",ChineseNames.Slot("Military01"));
Check.Equal("货舱舱门",ChineseNames.Module("modularcargobaydoor"));Check.Equal("巨蟒座舱",ChineseNames.Module("anaconda_cockpit"));
Check.Equal("伤害类型: 热能",new EngineeringModifier("DamageType",null,null,false,"$Thermic;").Display);
}
[Test] public void GlobalListSharesEngineerProgressAndSubtractsInventoryOnce()
{
var module=new FittedModule{Item="hpt_multicannon_gimbal_large"};var target=new RefitTarget("Overcharged Weapon",5,1,"",1,false,true);
var access=new EngineerAccess{Id=1,Name="Tod McQuinn",Progress="Unlocked",Rank=4,ReputationMin=94.6,ReputationMax=94.6};
var p=new PlayerState{Engineers=[access],Materials=[new("nickel","Nickel",4,0,"Raw")],Credits=100,CreditsReliable=true};
var list=new[]{new UpgradeListEntry(Guid.NewGuid(),module,target,2,Purchase:true,UnitPrice:75),new UpgradeListEntry(Guid.NewGuid(),module,target,1,Purchase:true)};
var budget=UpgradeListPlanner.Calculate(list,p,EngineeringCatalog.Default);
Check.Equal(3,budget.Engineering.Modules.Count);Check.Equal(150m,budget.KnownCredits);Check.Equal(50m,budget.MissingCredits!.Value);Check.Equal(1,budget.UnquotedItems);
var nickel=budget.Engineering.Materials.Single(m=>m.Key=="nickel");Check.Equal(4,nickel.Owned);Check.Equal(Math.Max(0,nickel.Required-4),nickel.Missing);
Check.That(budget.Engineering.Modules[0].Rolls>budget.Engineering.Modules[1].Rolls);
}
[Test] public void GlobalListRefusesDuplicateOwnedModulesAndStaleConfiguration()
{
var module=new FittedModule{Slot="LargeHardpoint1",Item="hpt_multicannon_gimbal_large"};var t=new RefitTarget("Overcharged Weapon",5,1,"",1,false,true);
var entry=new UpgradeListEntry(Guid.NewGuid(),module,t,1,"ship:7:LargeHardpoint1");
var p=new PlayerState{Ships=[new(){ShipId=7,ConfigurationChanged=true,Modules=[module]}]};
Check.Throws<InvalidOperationException>(()=>UpgradeListPlanner.Calculate([entry],p,EngineeringCatalog.Default));
Check.Throws<InvalidOperationException>(()=>UpgradeListPlanner.Calculate([entry with{Quantity=2}],p,EngineeringCatalog.Default));
}
[Test] public void GalaxyDirectoryUsesMeasuredCoordinatesAndPreservesInt64Address()
{
using var json=JsonDocument.Parse("""[{"name":"Sol","id64":9007199254740993,"coords":{"x":0,"y":0,"z":0}},{"name":"Missing coords"}]""");
var systems=GalaxyCatalog.Parse(json.RootElement);Check.Equal(1,systems.Count);Check.Equal(9007199254740993L,systems[0].SystemAddress!.Value);Check.Equal(0d,systems[0].Position.DistanceTo(new(0,0,0)));
}
[Test] public void ModuleReferencePricesKeepMissingAndConflictingPricesUnknown()
{
Check.Equal(633199m,ModulePrices.Find("int_hyperdrive_size7_class1")!.Value);
Check.That(ModulePrices.Find("int_fueltank_size3_class3") is null&&ModulePrices.Find("unknown_future_module") is null);
}
}