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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Execution;
using XFEEDToolBox.Core.Models;

namespace XFEEDToolBox.Core.Planning;

/// <summary>Only original active trade initiatives, exact destination identities and confirmed goods admit a CG sale edge.</summary>
public sealed class CommunityGoalSupplyScope
{
    private readonly Dictionary<long,HashSet<string>> accepted;
    private CommunityGoalSupplyScope(IReadOnlyList<CommunityGoalInfo> goals,Dictionary<long,HashSet<string>> accepted,string? issue)
    {Goals=goals;this.accepted=accepted;Issue=issue;}
    public IReadOnlyList<CommunityGoalInfo> Goals{get;}
    public string? Issue{get;}
    public bool Available=>accepted.Values.Any(goods=>goods.Count>0);

    public static CommunityGoalSupplyScope Create(MarketBook book,IReadOnlyList<CommunityGoalInfo>? catalogue,DateTimeOffset now,IReadOnlyCollection<string>? commodityFilter=null)
    {
        var confirmed=(catalogue??[]).GroupBy(goal=>goal.Id).Where(group=>group.Key is >0 and <=uint.MaxValue&&group.Count()==1).Select(group=>group.Single())
            .Where(goal=>goal.Active&&goal.Expires>now&&goal.MarketId>0&&goal.GoalType=="trade"&&goal.Activity.StartsWith("trade",StringComparison.Ordinal)
                &&!string.IsNullOrWhiteSpace(goal.SystemName)&&!string.IsNullOrWhiteSpace(goal.StationName)
                &&goal.AcceptedCommodities.Count>0&&goal.AcceptedCommodities.All(goods=>!string.IsNullOrWhiteSpace(CommodityCatalog.Key(goods))))
            .ToArray();
        var byMarket=book.Stations.GroupBy(station=>station.MarketId).ToDictionary(group=>group.Key,group=>group.ToArray());
        var matches=confirmed.Where(goal=>byMarket.TryGetValue(goal.MarketId,out var stations)&&stations.Length==1
            &&stations[0].SystemName.Equals(goal.SystemName,StringComparison.OrdinalIgnoreCase)&&stations[0].Name.Equals(goal.StationName,StringComparison.OrdinalIgnoreCase)).ToArray();
        var accepted=matches.GroupBy(goal=>goal.MarketId).ToDictionary(group=>group.Key,group=>group.SelectMany(goal=>goal.AcceptedCommodities)
            .Select(goods=>CommodityCatalog.Key(goods)).ToHashSet(StringComparer.Ordinal));
        var filter=TradeSearchConstraints.NormalizeCommodityFilter(commodityFilter).ToHashSet(StringComparer.Ordinal);
        if(filter.Count>0)foreach(var goods in accepted.Values)goods.IntersectWith(filter);
        var issue=matches.Length>0?accepted.Values.Any(goods=>goods.Count>0)?null:"商品筛选与有效 CG 的接收商品没有交集;请清空商品筛选或选择活动接收的商品。未回退普通跑商。":confirmed.Length>0
            ?"当前行情范围内没有身份匹配的 CG 交付站;请调整中心或半径并补全活动站行情。未回退普通跑商。"
            :"未确认仍有效的贸易 CG、交付站与接收商品,暂不能推荐 CG 供货路线。未回退普通跑商。";
        return new(matches,accepted,issue);
    }

    public bool AllowsSale(CommodityQuote quote)=>accepted.TryGetValue(quote.MarketId,out var goods)&&goods.Contains(CommodityCatalog.Key(quote.Commodity));

    public static bool MatchesRoute(IReadOnlyList<CommunityGoalInfo> catalogue,RoutePlan plan,DateTimeOffset now)
    {
        var stations=plan.Legs.SelectMany(leg=>new[]{leg.From,leg.To}).DistinctBy(station=>station.MarketId).ToArray();
        var scope=Create(new(stations,[]),catalogue,now,plan.Request.CommunityGoalCommodityFilter);
        var deliveries=plan.Legs.Where(leg=>leg.Orders.Count>0).ToArray();
        // Empty return legs are logistics. Every monetary delivery must serve
        // a currently valid CG; a single accepted item cannot bless unrelated cargo.
        return deliveries.Length>0&&deliveries.All(leg=>leg.Orders.All(order=>order.Quantity>0&&scope.accepted.TryGetValue(leg.To.MarketId,out var allowed)
            &&allowed.Contains(CommodityCatalog.Key(order.Commodity))&&scope.Goals.Any(goal=>goal.MarketId==leg.To.MarketId
            &&goal.SystemName.Equals(leg.To.SystemName,StringComparison.OrdinalIgnoreCase)&&goal.StationName.Equals(leg.To.Name,StringComparison.OrdinalIgnoreCase)
            &&goal.AcceptedCommodities.Select(goods=>CommodityCatalog.Key(goods)).Contains(CommodityCatalog.Key(order.Commodity),StringComparer.Ordinal))));
    }
}