mirror of
https://github.com/wangdage12/Snap.Hutao.git
synced 2026-07-31 04:10:25 +08:00
在养成计划,同步背包物品前面,加个 同步所有角色与武器 。 效果同 我的角色 养成计划 所有角色与武器 。
This commit is contained in:
@@ -2453,6 +2453,9 @@ Space Available: {2}</value>
|
|||||||
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
||||||
<value>Go</value>
|
<value>Go</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageCultivationSyncAllAvatarsAndWeapons" xml:space="preserve">
|
||||||
|
<value>Sync All Characters and Weapons</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
||||||
<value>Sync Inventory Items</value>
|
<value>Sync Inventory Items</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -2504,6 +2504,9 @@
|
|||||||
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
||||||
<value>前往</value>
|
<value>前往</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageCultivationSyncAllAvatarsAndWeapons" xml:space="preserve">
|
||||||
|
<value>同步所有角色与武器</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
||||||
<value>同步背包物品</value>
|
<value>同步背包物品</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -2429,6 +2429,9 @@
|
|||||||
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
<data name="ViewPageCultivationNavigateAction" xml:space="preserve">
|
||||||
<value>前往</value>
|
<value>前往</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageCultivationSyncAllAvatarsAndWeapons" xml:space="preserve">
|
||||||
|
<value>同步所有角色與武器</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
<data name="ViewPageCultivationRefreshInventory" xml:space="preserve">
|
||||||
<value>同步背包物品</value>
|
<value>同步背包物品</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Snap.Hutao.Factory.ContentDialog;
|
||||||
|
using Snap.Hutao.Model.Calculable;
|
||||||
|
using Snap.Hutao.Model.Cultivation;
|
||||||
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
|
using Snap.Hutao.Service.AvatarInfo.Factory;
|
||||||
|
using Snap.Hutao.Service.Cultivation.Consumption;
|
||||||
|
using Snap.Hutao.Service.Cultivation.Offline;
|
||||||
|
using Snap.Hutao.UI.Xaml.View.Dialog;
|
||||||
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
|
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using CalculatorAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
||||||
|
using CalculatorBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
|
||||||
|
using CalculatorConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
|
||||||
|
using CalculatorItemHelper = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.ItemHelper;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Cultivation;
|
||||||
|
|
||||||
|
[Service(ServiceLifetime.Singleton, typeof(IAvatarPropertyBatchCultivateService))]
|
||||||
|
internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPropertyBatchCultivateService
|
||||||
|
{
|
||||||
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
|
private readonly ICultivationService cultivationService;
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
[GeneratedConstructor]
|
||||||
|
public partial AvatarPropertyBatchCultivateService(IServiceProvider serviceProvider);
|
||||||
|
|
||||||
|
public async ValueTask<BatchCultivateResult?> ExecuteAsync(SummaryFactoryMetadataContext metadataContext, ImmutableArray<AvatarView> targetAvatars, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CultivateProjectAvatarPropertyBatchPreferences? batchPrefs = await cultivationService
|
||||||
|
.GetAvatarPropertyBatchCultivatePreferencesForCurrentProjectAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
CultivatePromotionDeltaBatchDialog dialog = batchPrefs is null
|
||||||
|
? await contentDialogFactory
|
||||||
|
.CreateInstanceAsync<CultivatePromotionDeltaBatchDialog>(serviceProvider)
|
||||||
|
.ConfigureAwait(false)
|
||||||
|
: await contentDialogFactory
|
||||||
|
.CreateInstanceAsync<CultivatePromotionDeltaBatchDialog>(serviceProvider, batchPrefs)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (await dialog.GetPromotionDeltaBaselineAsync().ConfigureAwait(false) is not (true, { } baseline))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await cultivationService
|
||||||
|
.SaveAvatarPropertyBatchCultivatePreferencesForCurrentProjectAsync(ToAvatarPropertyBatchPreferences(baseline))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(baseline.Delta.Weapon);
|
||||||
|
|
||||||
|
ContentDialog progressDialog = await contentDialogFactory
|
||||||
|
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyBatchCultivateProgressTitle)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
BatchCultivateResult result = default;
|
||||||
|
using (await contentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
|
||||||
|
{
|
||||||
|
await cultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableArray<CalculatorAvatarPromotionDelta>.Builder deltasBuilder = ImmutableArray.CreateBuilder<CalculatorAvatarPromotionDelta>();
|
||||||
|
foreach (AvatarView avatar in targetAvatars)
|
||||||
|
{
|
||||||
|
if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
|
||||||
|
{
|
||||||
|
++result.SkippedCount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltasBuilder.Add(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableArray<CalculatorAvatarPromotionDelta> deltas = deltasBuilder.ToImmutable();
|
||||||
|
|
||||||
|
CalculatorBatchConsumption batchConsumption = OfflineCalculator.CalculateBatchConsumption(deltas, metadataContext);
|
||||||
|
|
||||||
|
foreach ((CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta) in batchConsumption.Items.Zip(deltas))
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (!await SaveCultivationAsync(consumption, new CultivatePromotionDeltaOptions(delta, baseline.Strategy)).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++result.SucceedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CultivateProjectAvatarPropertyBatchPreferences ToAvatarPropertyBatchPreferences(CultivatePromotionDeltaOptions baseline)
|
||||||
|
{
|
||||||
|
CalculatorAvatarPromotionDelta d = baseline.Delta;
|
||||||
|
uint sa = 10;
|
||||||
|
uint se = 10;
|
||||||
|
uint sq = 10;
|
||||||
|
if (d.SkillList is [{ } a, { } e, { } q, ..])
|
||||||
|
{
|
||||||
|
sa = a.LevelTarget;
|
||||||
|
se = e.LevelTarget;
|
||||||
|
sq = q.LevelTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CultivateProjectAvatarPropertyBatchPreferences
|
||||||
|
{
|
||||||
|
AvatarLevelTarget = d.AvatarLevelTarget,
|
||||||
|
SkillATarget = sa,
|
||||||
|
SkillETarget = se,
|
||||||
|
SkillQTarget = sq,
|
||||||
|
WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U,
|
||||||
|
ConsumptionSaveStrategyIndex = (int)baseline.Strategy,
|
||||||
|
ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask<bool> SaveCultivationAsync(CalculatorConsumption consumption, CultivatePromotionDeltaOptions options)
|
||||||
|
{
|
||||||
|
LevelInformation levelInformation = LevelInformation.From(options.Delta);
|
||||||
|
|
||||||
|
InputConsumption avatarInput = new()
|
||||||
|
{
|
||||||
|
Type = CultivateType.AvatarAndSkill,
|
||||||
|
ItemId = options.Delta.AvatarId,
|
||||||
|
Items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume),
|
||||||
|
LevelInformation = levelInformation,
|
||||||
|
Strategy = options.Strategy,
|
||||||
|
};
|
||||||
|
|
||||||
|
ConsumptionSaveResult avatarSave = await cultivationService.SaveConsumptionAsync(avatarInput).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (avatarSave.Kind is ConsumptionSaveResultKind.NoProject)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(options.Delta.Weapon);
|
||||||
|
|
||||||
|
Guid? relatedAvatarEntryId = avatarSave.CreatedEntryInnerId;
|
||||||
|
if (relatedAvatarEntryId is null && avatarSave.Kind is ConsumptionSaveResultKind.Skipped)
|
||||||
|
{
|
||||||
|
relatedAvatarEntryId = await cultivationService.TryGetAvatarCultivateEntryInnerIdAsync(options.Delta.AvatarId).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedAvatarEntryId is null && avatarSave.Kind is ConsumptionSaveResultKind.NoItem)
|
||||||
|
{
|
||||||
|
relatedAvatarEntryId = await cultivationService.TryGetAvatarCultivateEntryInnerIdAsync(options.Delta.AvatarId).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedAvatarEntryId is null && !consumption.WeaponConsume.IsEmpty)
|
||||||
|
{
|
||||||
|
relatedAvatarEntryId = await cultivationService.EnsureAvatarAssociationStubAsync(options.Delta.AvatarId, levelInformation).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputConsumption weaponInput = new()
|
||||||
|
{
|
||||||
|
Type = CultivateType.Weapon,
|
||||||
|
ItemId = options.Delta.Weapon.Id,
|
||||||
|
Items = consumption.WeaponConsume,
|
||||||
|
LevelInformation = levelInformation,
|
||||||
|
Strategy = options.Strategy,
|
||||||
|
RelatedEntryId = relatedAvatarEntryId,
|
||||||
|
};
|
||||||
|
|
||||||
|
ConsumptionSaveResult weaponSave = await cultivationService.SaveConsumptionAsync(weaponInput).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return weaponSave.Kind is not ConsumptionSaveResultKind.NoProject;
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel.AvatarProperty;
|
namespace Snap.Hutao.Service.Cultivation;
|
||||||
|
|
||||||
internal struct BatchCultivateResult
|
internal struct BatchCultivateResult
|
||||||
{
|
{
|
||||||
public int SucceedCount;
|
public int SucceedCount;
|
||||||
public int SkippedCount;
|
public int SkippedCount;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Service.AvatarInfo.Factory;
|
||||||
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Cultivation;
|
||||||
|
|
||||||
|
internal interface IAvatarPropertyBatchCultivateService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see langword="null"/> when the baseline dialog is dismissed without confirmation.
|
||||||
|
/// </summary>
|
||||||
|
ValueTask<BatchCultivateResult?> ExecuteAsync(SummaryFactoryMetadataContext metadataContext, ImmutableArray<AvatarView> targetAvatars, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -467,6 +467,10 @@
|
|||||||
CommandParameter="{Binding Projects.CurrentItem, Mode=OneWay}"
|
CommandParameter="{Binding Projects.CurrentItem, Mode=OneWay}"
|
||||||
Icon="{shuxm:FontIcon Glyph=}"
|
Icon="{shuxm:FontIcon Glyph=}"
|
||||||
Label="{shuxm:ResourceString Name=ViewPageCultivationClearInventory}"/>
|
Label="{shuxm:ResourceString Name=ViewPageCultivationClearInventory}"/>
|
||||||
|
<AppBarButton
|
||||||
|
Command="{Binding SyncAllAvatarsAndWeaponsCommand}"
|
||||||
|
Icon="{shuxm:FontIcon Glyph=}"
|
||||||
|
Label="{shuxm:ResourceString Name=ViewPageCultivationSyncAllAvatarsAndWeapons}"/>
|
||||||
<AppBarButton Icon="{shuxm:FontIcon Glyph=}" Label="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}">
|
<AppBarButton Icon="{shuxm:FontIcon Glyph=}" Label="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}">
|
||||||
<AppBarButton.Flyout>
|
<AppBarButton.Flyout>
|
||||||
<MenuFlyout Placement="BottomEdgeAlignedRight">
|
<MenuFlyout Placement="BottomEdgeAlignedRight">
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Snap.Hutao.Service.AvatarInfo;
|
|||||||
using Snap.Hutao.Service.AvatarInfo.Factory;
|
using Snap.Hutao.Service.AvatarInfo.Factory;
|
||||||
using Snap.Hutao.Service.Cultivation;
|
using Snap.Hutao.Service.Cultivation;
|
||||||
using Snap.Hutao.Service.Cultivation.Consumption;
|
using Snap.Hutao.Service.Cultivation.Consumption;
|
||||||
|
using BatchCultivateResult = Snap.Hutao.Service.Cultivation.BatchCultivateResult;
|
||||||
using Snap.Hutao.Service.Cultivation.Offline;
|
using Snap.Hutao.Service.Cultivation.Offline;
|
||||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||||
using Snap.Hutao.Service.Notification;
|
using Snap.Hutao.Service.Notification;
|
||||||
@@ -28,7 +29,6 @@ using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using CalculatorAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
|
||||||
using CalculatorBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
|
using CalculatorBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
|
||||||
using CalculatorConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
|
using CalculatorConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
|
||||||
using CalculatorItemHelper = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.ItemHelper;
|
using CalculatorItemHelper = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.ItemHelper;
|
||||||
@@ -41,6 +41,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
{
|
{
|
||||||
private readonly ExclusiveTokenProvider refreshTokenProvider = new();
|
private readonly ExclusiveTokenProvider refreshTokenProvider = new();
|
||||||
private readonly AvatarPropertyViewModelScopeContext scopeContext;
|
private readonly AvatarPropertyViewModelScopeContext scopeContext;
|
||||||
|
private readonly IAvatarPropertyBatchCultivateService avatarPropertyBatchCultivateService;
|
||||||
|
|
||||||
private SummaryFactoryMetadataContext? metadataContext;
|
private SummaryFactoryMetadataContext? metadataContext;
|
||||||
|
|
||||||
@@ -270,69 +271,16 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
targetAvatars = [.. avatars.Source];
|
targetAvatars = [.. avatars.Source];
|
||||||
}
|
}
|
||||||
|
|
||||||
CultivateProjectAvatarPropertyBatchPreferences? batchPrefs = await scopeContext.CultivationService
|
ArgumentNullException.ThrowIfNull(metadataContext);
|
||||||
.GetAvatarPropertyBatchCultivatePreferencesForCurrentProjectAsync()
|
BatchCultivateResult? batchResult = await avatarPropertyBatchCultivateService
|
||||||
|
.ExecuteAsync(metadataContext, targetAvatars, CancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
CultivatePromotionDeltaBatchDialog dialog = batchPrefs is null
|
if (batchResult is not { } result)
|
||||||
? await scopeContext.ContentDialogFactory
|
|
||||||
.CreateInstanceAsync<CultivatePromotionDeltaBatchDialog>(scopeContext.ServiceProvider)
|
|
||||||
.ConfigureAwait(false)
|
|
||||||
: await scopeContext.ContentDialogFactory
|
|
||||||
.CreateInstanceAsync<CultivatePromotionDeltaBatchDialog>(scopeContext.ServiceProvider, batchPrefs)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (await dialog.GetPromotionDeltaBaselineAsync().ConfigureAwait(false) is not (true, { } baseline))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await scopeContext.CultivationService
|
|
||||||
.SaveAvatarPropertyBatchCultivatePreferencesForCurrentProjectAsync(ToAvatarPropertyBatchPreferences(baseline))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(baseline.Delta.Weapon);
|
|
||||||
|
|
||||||
ContentDialog progressDialog = await scopeContext.ContentDialogFactory
|
|
||||||
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyBatchCultivateProgressTitle)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
BatchCultivateResult result = default;
|
|
||||||
using (await scopeContext.ContentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
|
|
||||||
{
|
|
||||||
await scopeContext.CultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableArray<CalculatorAvatarPromotionDelta>.Builder deltasBuilder = ImmutableArray.CreateBuilder<CalculatorAvatarPromotionDelta>();
|
|
||||||
foreach (AvatarView avatar in targetAvatars)
|
|
||||||
{
|
|
||||||
if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
|
|
||||||
{
|
|
||||||
++result.SkippedCount;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
deltasBuilder.Add(copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableArray<CalculatorAvatarPromotionDelta> deltas = deltasBuilder.ToImmutable();
|
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(metadataContext);
|
|
||||||
CalculatorBatchConsumption batchConsumption = OfflineCalculator.CalculateBatchConsumption(deltas, metadataContext);
|
|
||||||
|
|
||||||
foreach ((CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta) in batchConsumption.Items.Zip(deltas))
|
|
||||||
{
|
|
||||||
if (!await SaveCultivationAsync(consumption, new CultivatePromotionDeltaOptions(delta, baseline.Strategy), true).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++result.SucceedCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scopeContext.Messenger.Send(CultivationProjectEntriesChangedMessage.Empty);
|
scopeContext.Messenger.Send(CultivationProjectEntriesChangedMessage.Empty);
|
||||||
|
|
||||||
InfoBarMessage message = result.SkippedCount > 0
|
InfoBarMessage message = result.SkippedCount > 0
|
||||||
@@ -342,31 +290,6 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
scopeContext.Messenger.Send(message);
|
scopeContext.Messenger.Send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CultivateProjectAvatarPropertyBatchPreferences ToAvatarPropertyBatchPreferences(CultivatePromotionDeltaOptions baseline)
|
|
||||||
{
|
|
||||||
CalculatorAvatarPromotionDelta d = baseline.Delta;
|
|
||||||
uint sa = 10;
|
|
||||||
uint se = 10;
|
|
||||||
uint sq = 10;
|
|
||||||
if (d.SkillList is [{ } a, { } e, { } q, ..])
|
|
||||||
{
|
|
||||||
sa = a.LevelTarget;
|
|
||||||
se = e.LevelTarget;
|
|
||||||
sq = q.LevelTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CultivateProjectAvatarPropertyBatchPreferences
|
|
||||||
{
|
|
||||||
AvatarLevelTarget = d.AvatarLevelTarget,
|
|
||||||
SkillATarget = sa,
|
|
||||||
SkillETarget = se,
|
|
||||||
SkillQTarget = sq,
|
|
||||||
WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U,
|
|
||||||
ConsumptionSaveStrategyIndex = (int)baseline.Strategy,
|
|
||||||
ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <returns><see langword="true"/> if we can continue saving consumptions, otherwise <see langword="false"/>.</returns>
|
/// <returns><see langword="true"/> if we can continue saving consumptions, otherwise <see langword="false"/>.</returns>
|
||||||
private async ValueTask<bool> SaveCultivationAsync(CalculatorConsumption consumption, CultivatePromotionDeltaOptions options, bool isBatch = false)
|
private async ValueTask<bool> SaveCultivationAsync(CalculatorConsumption consumption, CultivatePromotionDeltaOptions options, bool isBatch = false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,19 +11,24 @@ using Snap.Hutao.Core.Logging;
|
|||||||
using Snap.Hutao.Core.Setting;
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Factory.ContentDialog;
|
using Snap.Hutao.Factory.ContentDialog;
|
||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using Snap.Hutao.Service.AvatarInfo;
|
||||||
|
using Snap.Hutao.Service.AvatarInfo.Factory;
|
||||||
using Snap.Hutao.Service.Cultivation;
|
using Snap.Hutao.Service.Cultivation;
|
||||||
using Snap.Hutao.Service.Inventory;
|
using Snap.Hutao.Service.Inventory;
|
||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||||
using Snap.Hutao.Service.Navigation;
|
using Snap.Hutao.Service.Navigation;
|
||||||
using Snap.Hutao.Service.Notification;
|
using Snap.Hutao.Service.Notification;
|
||||||
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.Service.Yae;
|
using Snap.Hutao.Service.Yae;
|
||||||
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
using Snap.Hutao.UI.Xaml.Control.AutoSuggestBox;
|
using Snap.Hutao.UI.Xaml.Control.AutoSuggestBox;
|
||||||
using Snap.Hutao.UI.Xaml.Data;
|
using Snap.Hutao.UI.Xaml.Data;
|
||||||
using Snap.Hutao.UI.Xaml.View.Dialog;
|
using Snap.Hutao.UI.Xaml.View.Dialog;
|
||||||
using Snap.Hutao.ViewModel.Game;
|
using Snap.Hutao.ViewModel.Game;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using BatchCultivateResult = Snap.Hutao.Service.Cultivation.BatchCultivateResult;
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel.Cultivation;
|
namespace Snap.Hutao.ViewModel.Cultivation;
|
||||||
|
|
||||||
@@ -38,6 +43,9 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec
|
|||||||
private readonly ICultivationService cultivationService;
|
private readonly ICultivationService cultivationService;
|
||||||
private readonly INavigationService navigationService;
|
private readonly INavigationService navigationService;
|
||||||
private readonly IInventoryService inventoryService;
|
private readonly IInventoryService inventoryService;
|
||||||
|
private readonly IAvatarInfoService avatarInfoService;
|
||||||
|
private readonly IAvatarPropertyBatchCultivateService avatarPropertyBatchCultivateService;
|
||||||
|
private readonly IUserService userService;
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
private readonly IMetadataService metadataService;
|
private readonly IMetadataService metadataService;
|
||||||
private readonly ITaskContext taskContext;
|
private readonly ITaskContext taskContext;
|
||||||
@@ -322,6 +330,57 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Command("SyncAllAvatarsAndWeaponsCommand")]
|
||||||
|
private async Task SyncAllAvatarsAndWeaponsAsync()
|
||||||
|
{
|
||||||
|
SentrySdk.AddBreadcrumb(BreadcrumbFactory2.CreateUI("Sync all avatars and weapons to cultivation", "CultivationViewModel.Command", []));
|
||||||
|
|
||||||
|
if (Projects?.CurrentItem is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
|
||||||
|
{
|
||||||
|
messenger.Send(InfoBarMessage.Warning(SH.MustSelectUserAndUid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SummaryFactoryMetadataContext summaryContext = await metadataService.GetContextAsync<SummaryFactoryMetadataContext>(CancellationToken).ConfigureAwait(false);
|
||||||
|
Summary? summary = await avatarInfoService.GetSummaryAsync(summaryContext, userAndUid, global::Snap.Hutao.Service.AvatarInfo.RefreshOptionKind.None, CancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (summary is not { Avatars: { } avatars })
|
||||||
|
{
|
||||||
|
messenger.Send(InfoBarMessage.Warning(SH.ViewPageAvatarPropertyDefaultDescription));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avatars.Source.Count < 1)
|
||||||
|
{
|
||||||
|
messenger.Send(InfoBarMessage.Warning(SH.ViewPageAvatarPropertyDefaultDescription));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableArray<AvatarView> targetAvatars = [.. avatars.Source];
|
||||||
|
|
||||||
|
BatchCultivateResult? batchResult = await avatarPropertyBatchCultivateService
|
||||||
|
.ExecuteAsync(summaryContext, targetAvatars, CancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (batchResult is not { } result)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
messenger.Send(CultivationProjectEntriesChangedMessage.Empty);
|
||||||
|
|
||||||
|
InfoBarMessage message = result.SkippedCount > 0
|
||||||
|
? InfoBarMessage.Warning(SH.FormatViewModelCultivationBatchAddIncompleted(result.SucceedCount, result.SkippedCount))
|
||||||
|
: InfoBarMessage.Success(SH.FormatViewModelCultivationBatchAddCompleted(result.SucceedCount, result.SkippedCount));
|
||||||
|
|
||||||
|
messenger.Send(message);
|
||||||
|
}
|
||||||
|
|
||||||
[Command("ClearInventoryCommand")]
|
[Command("ClearInventoryCommand")]
|
||||||
private async Task ClearInventoryAsync(CultivateProject? project)
|
private async Task ClearInventoryAsync(CultivateProject? project)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user