using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using XFEEDToolBox.Core.Galaxy; using XFEEDToolBox.Core.Localization; namespace XFEEDToolBox.ViewModels; public sealed record GalacticPlaceChoice(string Name) { public string DisplayName=>ChineseNames.Translate(Name) is var n&&n!="未收录名称"?n:Name; public string OriginalName=>DisplayName==Name?"":Name; } public partial class ToolboxViewModel { private readonly Dictionary> placeChoices=[]; private GalacticPlaces? placesClient; private GalacticPlaces PlacesClient=>placesClient??=new(galaxyHttp); private int placeSearchVersion; [ObservableProperty,NotifyPropertyChangedFor(nameof(PlacesNeedTrader)),NotifyPropertyChangedFor(nameof(PlacesNeedEngineer)),NotifyPropertyChangedFor(nameof(PlacesNeedItem)),NotifyPropertyChangedFor(nameof(PlacesNeedModule)),NotifyPropertyChangedFor(nameof(PlacesNeedGathering)),NotifyPropertyChangedFor(nameof(PlacesNeedGatheringMaterial)),NotifyPropertyChangedFor(nameof(PlacesAllowPadFilter))] public partial int GalaxyPlaceKindIndex {get;set;} public bool PlacesNeedTrader=>GalaxyPlaceKindIndex==0; public bool PlacesNeedEngineer=>GalaxyPlaceKindIndex==2; public bool PlacesNeedItem=>GalaxyPlaceKindIndex is >=3 and <=5; public bool PlacesNeedModule=>GalaxyPlaceKindIndex==4; public bool PlacesNeedGathering=>GalaxyPlaceKindIndex==6; public bool PlacesNeedGatheringMaterial=>PlacesNeedGathering&&GalaxyGatheringCategoryIndex!=2; public bool PlacesAllowPadFilter=>!PlacesNeedGathering&&GalaxyPlaceKindIndex!=2; [ObservableProperty,NotifyPropertyChangedFor(nameof(PlacesNeedGatheringMaterial)),NotifyPropertyChangedFor(nameof(GalaxyGatheringChoices)),NotifyPropertyChangedFor(nameof(GalaxyGatheringHint))] public partial int GalaxyGatheringCategoryIndex {get;set;} [ObservableProperty,NotifyPropertyChangedFor(nameof(GalaxyGatheringHint))] public partial GatheringMaterial? GalaxyGatheringMaterial {get;set;}=MaterialGathering.Choices(GatheringCategory.Manufactured).FirstOrDefault(); public IReadOnlyList GalaxyGatheringChoices=>MaterialGathering.Choices((GatheringCategory)Math.Clamp(GalaxyGatheringCategoryIndex,0,2)); public string GalaxyGatheringHint=>GalaxyGatheringCategoryIndex switch { 0=>"G5 人造材料 · "+(GalaxyGatheringMaterial is {} m?MaterialGathering.Rule(m.Name).Description: "请选择材料")+";按星系势力与派系当前状态筛选最近候选,抵达后扫描高等级信号。", 1=>"按所选材料筛选图中的脑树采集点,按当前位置距离排序;结果包含行星及起止地表坐标。", _=>"Jameson 坠毁点 · HIP 12099 1 B · 扫描数据信标;可在数据贸易商兑换其他数据。" }; partial void OnGalaxyGatheringCategoryIndexChanged(int value) { GalaxyGatheringMaterial=GalaxyGatheringChoices.FirstOrDefault();InvalidateGatheringResults(); } partial void OnGalaxyGatheringMaterialChanged(GatheringMaterial? value)=>InvalidateGatheringResults(); private void InvalidateGatheringResults() { placeSearchVersion++; if(SearchGalacticPlacesCommand.IsRunning)SearchGalacticPlacesCommand.Cancel(); GalaxyPlaces=[];GalaxyPlacesStatus="以当前位置查找材料采集点。"; } [ObservableProperty] public partial int GalaxyTraderIndex {get;set;} [ObservableProperty] public partial int GalaxyModuleClassIndex {get;set;} [ObservableProperty] public partial string GalaxyModuleRating {get;set;}="全部"; [ObservableProperty] public partial bool GalaxyPlaceLargePad {get;set;} [ObservableProperty] public partial string GalaxyPlaceQuery {get;set;}=""; [ObservableProperty] public partial bool GalaxyPlacesBusy {get;set;} [ObservableProperty] public partial string GalaxyPlacesStatus {get;set;}="以当前位置查找;商品与装配库存以最新采集记录为准。"; [ObservableProperty] public partial IReadOnlyList GalaxyPlaces {get;set;}=[]; [ObservableProperty] public partial EngineerLocation? GalaxyEngineer {get;set;}=EngineerDirectory.All.FirstOrDefault(e=>e.Name.StartsWith("Tod ")); public IReadOnlyList GalaxyEngineers=>EngineerDirectory.All; public IReadOnlyList GalaxyModuleClasses {get;}=["全部","0","1","2","3","4","5","6","7","8"]; public IReadOnlyList GalaxyModuleRatings {get;}=["全部","A","B","C","D","E","F","G","H","I"]; private void InvalidatePlaceResults() { placeSearchVersion++;if(SearchGalacticPlacesCommand.IsRunning)SearchGalacticPlacesCommand.Cancel(); GalaxyPlaces=[];GalaxyPlacesStatus="以当前位置查找;商品与装配库存以最新采集记录为准。"; } partial void OnGalaxyPlaceKindIndexChanged(int value){InvalidatePlaceResults();GalaxyPlaceQuery="";if(value==6)GalaxyPlacesStatus="选择材料类别和材料后查找采集点。";} partial void OnGalaxyTraderIndexChanged(int value)=>InvalidatePlaceResults(); partial void OnGalaxyModuleClassIndexChanged(int value)=>InvalidatePlaceResults(); partial void OnGalaxyModuleRatingChanged(string value)=>InvalidatePlaceResults(); partial void OnGalaxyPlaceLargePadChanged(bool value)=>InvalidatePlaceResults(); partial void OnGalaxyPlaceQueryChanged(string value)=>InvalidatePlaceResults(); partial void OnGalaxyEngineerChanged(EngineerLocation? value)=>InvalidatePlaceResults(); internal async Task> SuggestPlacesAsync(string query,CancellationToken token) { if(!PlacesNeedItem)return []; var kind=(GalacticPlaceKind)GalaxyPlaceKindIndex; if(!placeChoices.TryGetValue(kind,out var values))placeChoices[kind]=values=await PlacesClient.ChoicesAsync(kind,token); token.ThrowIfCancellationRequested();query=query.Trim(); return values.Select(s=>new GalacticPlaceChoice(s)).Where(c=>c.Name.Contains(query,StringComparison.OrdinalIgnoreCase)||c.DisplayName.Contains(query,StringComparison.OrdinalIgnoreCase)).ToArray(); } [RelayCommand] private async Task SearchGalacticPlacesAsync(CancellationToken cancellationToken=default) { using var stop=CancellationTokenSource.CreateLinkedTokenSource(lifetime.Token,cancellationToken);var token=stop.Token;var version=placeSearchVersion;GalaxyPlacesBusy=true; try { var origin=CurrentPlayer.Position??throw new InvalidOperationException("尚未读取当前星系坐标。"); var kind=(GalacticPlaceKind)Math.Clamp(GalaxyPlaceKindIndex,0,6); IReadOnlyList results; if(kind==GalacticPlaceKind.MaterialGathering) { var category=(GatheringCategory)Math.Clamp(GalaxyGatheringCategoryIndex,0,2); var material=GalaxyGatheringMaterial?.Name??"";GalaxyPlacesStatus="正在查找最近材料采集点…"; results=category==GatheringCategory.Manufactured ?await new MaterialGathering(galaxyHttp).SearchManufacturedAsync(material,origin,token) :MaterialGathering.FixedPlaces(category,material,origin); } else if(kind==GalacticPlaceKind.Engineer) { var engineer=GalaxyEngineer??throw new InvalidOperationException("请先选择工程师。"); results=[new(engineer.DisplayName,engineer.SystemName,engineer.Position,null,origin.DistanceTo(engineer.Position),engineer.BaseName+" · "+engineer.Body,"工程师驻地",engineer.Portrait)]; } else { var value=kind==GalacticPlaceKind.MaterialTrader?new[]{"Raw","Manufactured","Encoded"}[Math.Clamp(GalaxyTraderIndex,0,2)]:GalaxyPlaceQuery; GalaxyPlacesStatus="正在查找最近地点…"; results=await PlacesClient.SearchAsync(kind,value,origin,GalaxyModuleClassIndex==0?null:GalaxyModuleClassIndex-1,GalaxyModuleRating=="全部"?"":GalaxyModuleRating,GalaxyPlaceLargePad,token); } token.ThrowIfCancellationRequested();GalaxyPlaces=results; foreach(var result in results)galaxyCache[result.SystemName]=result.System; PublishGalaxy(); GalaxyPlacesStatus=results.Count>0?$"找到 {results.Count} 个地点 · 按距离排序"+(kind is GalacticPlaceKind.Engineer or GalacticPlaceKind.MaterialGathering?"":" · Spansh 采集数据"): kind==GalacticPlaceKind.MaterialGathering?"未找到符合材料筛选条件的已上报星系。":"没有符合条件的已上报站点。"; if(results.FirstOrDefault() is {} first)ShowGalacticPlace(first); } catch(OperationCanceledException){if(version==placeSearchVersion)GalaxyPlacesStatus="地点查找已取消。";} catch(Exception error){if(version==placeSearchVersion)GalaxyPlacesStatus="地点查找未完成:"+error.Message;} finally{GalaxyPlacesBusy=false;} } internal void ShowGalacticPlace(GalacticPlace place) { galaxyCache[place.SystemName]=place.System;GalaxySelection=place.System;GalaxyCentre=place.Position;PublishGalaxy(); } }