XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Outfitting;
using XFEEDToolBox.Core.Localization;
namespace XFEEDToolBox.Core.Planning;

public sealed record UpgradeListEntry(Guid Id,FittedModule Module,RefitTarget Target,int Quantity,string SourceKey="",bool Purchase=false,decimal? UnitPrice=null,string PriceSource="手动报价")
{
    public string Name=>Module.DisplayName;
    public string OriginalName=>Module.OriginalName;
    public string TargetName=>$"{ChineseNames.Translate(Target.Blueprint)} · G{Target.Grade} · {Target.Quality:P0} · "+(Target.Experimental.Length>0?ChineseNames.Translate(Target.Experimental):"无实验效果");
    public string TargetOriginal=>ChineseNames.English(Target.Blueprint)+" · "+(Target.Experimental.Length>0?ChineseNames.English(Target.Experimental):"None");
    public string Detail=>$"{Quantity} 件 · {(SourceKey.Length>0?"使用现有模块进度":"从未改装开始")}"+(Purchase?(UnitPrice is {} price?$" · {price:N0} Cr/件 · {PriceSource}":" · 购买价待报价"):" · 仅工程材料");
}
public sealed record UpgradeListBudget(ShipRefitResult Engineering,decimal KnownCredits,int UnquotedItems,decimal? AvailableCredits)
{
    public decimal? MissingCredits=>AvailableCredits is {} cash?Math.Max(0,KnownCredits-cash):null;
}
public static class UpgradeListPlanner
{
    public static IReadOnlyList<UpgradeListEntry> AddShip(IReadOnlyList<UpgradeListEntry> entries,ShipRefitDocument document)
    {
        var requested=document.Slots.Where(s=>s.Module is not null&&s.Target is not null).ToArray();
        if(requested.Length==0)throw new InvalidOperationException("请先为模块设定工程改装目标,再添加至清单。");
        var result=entries.ToList();
        foreach(var slot in requested)
        {
            var source=slot.InstanceKey;
            var added=new UpgradeListEntry(Guid.NewGuid(),slot.Module!,slot.Target!,1,source,source.Length==0,source.Length==0?ModulePrices.Find(slot.Module!.Item):null,"模块参考基础价");
            var existing=source.Length>0?result.FindIndex(e=>e.SourceKey==source):-1;
            if(existing>=0)result[existing]=added with{Id=result[existing].Id};else result.Add(added);
        }
        if(result.Sum(e=>e.Quantity)>100)throw new InvalidOperationException("清单最多支持 100 件模块。");
        return result;
    }
    public static UpgradeListBudget Calculate(IReadOnlyList<UpgradeListEntry> entries,PlayerState p,EngineeringCatalog catalog,CancellationToken token=default)
    {
        if(entries.Sum(e=>e.Quantity)>100||entries.Any(e=>e.Quantity is <1 or >100||e.UnitPrice<0))throw new InvalidOperationException("清单最多支持 100 件模块,数量与价格必须有效。");
        var slots=new List<RefitSlot>();var owned=new HashSet<string>();decimal credits=0;var unknown=0;
        foreach(var entry in entries)
        {
            var module=entry.Module;
            if(entry.SourceKey.Length>0)
            {
                if(entry.Quantity!=1||!owned.Add(entry.SourceKey))throw new InvalidOperationException("同一件已有模块只能在清单中使用一次。");
                var parts=entry.SourceKey.Split(':',3);
                if(parts.Length==3&&parts[0]=="ship"&&long.TryParse(parts[1],out var id))
                {
                    var ship=p.Ships.FirstOrDefault(s=>s.ShipId==id);
                    if(ship is null||ship.ConfigurationChanged||ship.ConfigurationAt is null)throw new InvalidOperationException("清单中已有模块的完整装配尚未读取。");
                    module=ship.Modules.FirstOrDefault(m=>m.Slot==parts[2]&&m.Item.Equals(entry.Module.Item,StringComparison.OrdinalIgnoreCase))??throw new InvalidOperationException("清单中的已有模块已被卸下或更换,请重新选择。");
                }
                else if(parts.Length==2&&parts[0]=="store"&&long.TryParse(parts[1],out var storage))
                {
                    var stored=p.StoredModules.FirstOrDefault(s=>s.StorageSlot==storage&&s.Item.Equals(module.Item,StringComparison.OrdinalIgnoreCase)&&!s.InTransit)
                        ??throw new InvalidOperationException("清单中的寄存模块已移动或更换,请重新选择。");
                    module=module with{Engineering=stored.Engineering.Length==0?null:new(){Blueprint=stored.Engineering,Level=stored.EngineeringLevel??0,Quality=stored.EngineeringQuality}};
                }
                else throw new InvalidOperationException("清单中的模块来源无效。");
            }
            for(var n=0;n<entry.Quantity;n++)slots.Add(new(){Slot=$"list:{entry.Id}:{n}",Module=module,Target=entry.Target,Origin="全局改装清单"});
            if(entry.Purchase){if(entry.UnitPrice is {} unit)credits=checked(credits+unit*entry.Quantity);else unknown+=entry.Quantity;}
        }
        return new(ShipRefitPlanner.Calculate(new(0,"","全局改装清单",null,slots),catalog,p.Engineers,p.Materials,token),credits,unknown,p.CreditsReliable?p.Credits:null);
    }
}