Skip to content

Commit

Permalink
Add raid adventurers
Browse files Browse the repository at this point in the history
  • Loading branch information
SapiensAnatis committed Jul 24, 2023
1 parent 5e8b3c0 commit 65086f9
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 53 deletions.
5 changes: 4 additions & 1 deletion DragaliaAPI.Database/Entities/DbPlayerCharaData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,10 @@ public DbPlayerCharaData() { }
/// User-facing constructor.
/// </summary>
/// <param name="deviceAccountId">Primary key.</param>
/// <param name="id"></param>
/// <param name="isTemporary"></param>
[SetsRequiredMembers]
public DbPlayerCharaData(string deviceAccountId, Charas id)
public DbPlayerCharaData(string deviceAccountId, Charas id, bool isTemporary = false)
{
CharaData data = MasterAsset.CharaData.Get(id);

Expand Down Expand Up @@ -210,5 +212,6 @@ public DbPlayerCharaData(string deviceAccountId, Charas id)
this.Ability2Level = (byte)data.DefaultAbility2Level;
this.Ability3Level = (byte)data.DefaultAbility3Level;
this.IsUnlockEditSkill = data.Availability == CharaAvailabilities.Story;
this.IsTemporary = false;
}
}
8 changes: 6 additions & 2 deletions DragaliaAPI.Database/Repositories/IUnitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ public interface IUnitRepository

Task<bool> CheckHasDragons(IEnumerable<Dragons> idList);

Task<IEnumerable<(Charas id, bool isNew)>> AddCharas(IEnumerable<Charas> idList);
Task<IEnumerable<(Charas id, bool isNew)>> AddCharas(
IEnumerable<Charas> idList,
bool isTemporary = false
);

Task<bool> AddCharas(Charas id);
Task<bool> AddCharas(Charas id, bool isTemporary = false);

Task<IEnumerable<(Dragons id, bool isNew)>> AddDragons(IEnumerable<Dragons> idList);

Expand All @@ -36,4 +39,5 @@ public interface IUnitRepository
Task<IDictionary<Charas, IEnumerable<DbSetUnit>>> GetCharaSets(IEnumerable<Charas> charaId);

Task<DbPlayerCharaData?> FindCharaAsync(Charas chara);
Task ClearIsTemporary(Charas id);
}
27 changes: 22 additions & 5 deletions DragaliaAPI.Database/Repositories/UnitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,15 @@ public async Task<bool> CheckHasDragons(IEnumerable<Dragons> idList)
/// <summary>
/// Add a list of characters to the database. Will only add the first instance of any new character.
/// </summary>
/// <param name="this.playerIdentityService.AccountId"></param>
/// <param name="idList"></param>
/// <param name="isTemporary"></param>
/// <param name="this.playerIdentityService.AccountId"></param>
/// <returns>A list of tuples which adds an additional dimension onto the input list,
/// where the second item shows whether the given character id was a duplicate.</returns>
public async Task<IEnumerable<(Charas id, bool isNew)>> AddCharas(IEnumerable<Charas> idList)
public async Task<IEnumerable<(Charas id, bool isNew)>> AddCharas(
IEnumerable<Charas> idList,
bool isTemporary = false
)
{
List<Charas> addedChars = idList.ToList();

Expand All @@ -106,7 +110,7 @@ public async Task<bool> CheckHasDragons(IEnumerable<Dragons> idList)
if (newCharas.Any())
{
IEnumerable<DbPlayerCharaData> dbEntries = newCharas.Select(
id => new DbPlayerCharaData(this.playerIdentityService.AccountId, id)
id => new DbPlayerCharaData(this.playerIdentityService.AccountId, id, isTemporary)
);

await apiContext.PlayerCharaData.AddRangeAsync(dbEntries);
Expand Down Expand Up @@ -147,9 +151,22 @@ out StoryData? story
return newMapping;
}

public async Task<bool> AddCharas(Charas id)
public async Task<bool> AddCharas(Charas id, bool isTemporary = false)
{
return (await this.AddCharas(new[] { id })).First().isNew;
return (await this.AddCharas(new[] { id }, isTemporary)).First().isNew;
}

public async Task ClearIsTemporary(Charas id)
{
DbPlayerCharaData? chara = await this.Charas.FirstOrDefaultAsync(x => x.CharaId == id);
if (chara is null)
{
logger.LogWarning("Attempted to update temp flag of unowned character: {id}", id);
return;
}

logger.LogDebug("Set {id}.IsTemporary = false", id);
chara.IsTemporary = false;
}

public async Task<IEnumerable<(Dragons id, bool isNew)>> AddDragons(IEnumerable<Dragons> idList)
Expand Down
4 changes: 3 additions & 1 deletion DragaliaAPI.Shared/MasterAsset/Models/Event/EventData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public record EventData(
EntityTypes ViewEntityType4,
int ViewEntityId4,
EntityTypes ViewEntityType5,
int ViewEntityId5
int ViewEntityId5,
Charas EventCharaId,
int GuestJoinStoryId
);
3 changes: 2 additions & 1 deletion DragaliaAPI.Test/Services/DragonServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,8 @@ public async Task DoDragonResetPlusCount_ResetsPlusCount()
50,
null,
null,
null
null,
false
)
)
)
Expand Down
10 changes: 9 additions & 1 deletion DragaliaAPI.Test/Services/StoryServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,15 @@ public async Task ReadQuestStory_DragonReward_ReceivesReward()
.Setup(
x =>
x.GrantReward(
new Entity(EntityTypes.Dragon, (int)Dragons.Brunhilda, 1, null, null, null)
new Entity(
EntityTypes.Dragon,
(int)Dragons.Brunhilda,
1,
null,
null,
null,
false
)
)
)
.ReturnsAsync(RewardGrantResult.Added);
Expand Down
16 changes: 14 additions & 2 deletions DragaliaAPI/Features/Event/EventRepository.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
using DragaliaAPI.Database;
using DragaliaAPI.Database.Entities;
using DragaliaAPI.Database.Repositories;
using DragaliaAPI.Models;
using DragaliaAPI.Services.Exceptions;
using DragaliaAPI.Shared.PlayerDetails;
using Microsoft.EntityFrameworkCore;

namespace DragaliaAPI.Features.Event;

public class EventRepository(ApiContext apiContext, IPlayerIdentityService playerIdentityService)
: IEventRepository
public class EventRepository(
ApiContext apiContext,
IPlayerIdentityService playerIdentityService,
IUserDataRepository userDataRepository
) : IEventRepository
{
public IQueryable<DbPlayerEventData> EventData =>
apiContext.PlayerEventData.Where(x => x.DeviceAccountId == playerIdentityService.AccountId);

public IQueryable<DbPlayerEventData> MemoryEventData =>
EventData.Join(
userDataRepository.UserData,
eventData => eventData.EventId,
userData => userData.ActiveMemoryEventId,
(eventData, userData) => eventData
);

public IQueryable<DbPlayerEventReward> Rewards =>
apiContext.PlayerEventRewards.Where(
x => x.DeviceAccountId == playerIdentityService.AccountId
Expand Down
29 changes: 28 additions & 1 deletion DragaliaAPI/Features/Event/EventService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class EventService(
ILogger<EventService> logger,
IEventRepository eventRepository,
IRewardService rewardService,
IQuestRepository questRepository
IQuestRepository questRepository,
IUnitRepository unitRepository

Check warning on line 20 in DragaliaAPI/Features/Event/EventService.cs

View workflow job for this annotation

GitHub Actions / test (DragaliaAPI.Test)

Parameter 'unitRepository' is unread.

Check warning on line 20 in DragaliaAPI/Features/Event/EventService.cs

View workflow job for this annotation

GitHub Actions / test (DragaliaAPI.Integration.Test)

Parameter 'unitRepository' is unread.

Check warning on line 20 in DragaliaAPI/Features/Event/EventService.cs

View workflow job for this annotation

GitHub Actions / test (DragaliaAPI.Database.Test)

Parameter 'unitRepository' is unread.
) : IEventService
{
public async Task<bool> GetCustomEventFlag(int eventId)
Expand Down Expand Up @@ -191,6 +192,32 @@ public async Task CreateEventData(int eventId)

if (neededEventPassiveIds.Count > 0)
eventRepository.CreateEventPassives(eventId, neededEventPassiveIds);

// Memory events give their characters as temporary on starting
if (data.EventCharaId != Charas.Empty && data.IsMemoryEvent)
{
await rewardService.GrantReward(
new Entity(Type: EntityTypes.Chara, Id: (int)data.EventCharaId, IsTemporary: true)
);
}
}

public async Task<EventData?> GetMemoryEventAssetData()
{
int? memoryEventId = await eventRepository.MemoryEventData
.Select(x => x.EventId)
.Cast<int?>()
.FirstOrDefaultAsync();

if (
memoryEventId is null
|| MasterAsset.EventData.TryGetValue(memoryEventId.Value, out EventData? result)
)
{
return null;
}

return result;
}

private async Task<DbPlayerEventData> GetEventData(int eventId)
Expand Down
1 change: 1 addition & 0 deletions DragaliaAPI/Features/Event/IEventRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace DragaliaAPI.Features.Event;
public interface IEventRepository
{
IQueryable<DbPlayerEventData> EventData { get; }
IQueryable<DbPlayerEventData> MemoryEventData { get; }
IQueryable<DbPlayerEventReward> Rewards { get; }
IQueryable<DbPlayerEventItem> Items { get; }
IQueryable<DbPlayerEventPassive> Passives { get; }
Expand Down
3 changes: 3 additions & 0 deletions DragaliaAPI/Features/Event/IEventService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using DragaliaAPI.Models.Generated;
using DragaliaAPI.Shared.MasterAsset.Models.Event;

namespace DragaliaAPI.Features.Event;

Expand Down Expand Up @@ -37,4 +38,6 @@ int locationId
Task<SimpleEventUserList> GetSimpleEventUserData(int eventId);

#endregion

Task<EventData?> GetMemoryEventAssetData();
}
3 changes: 2 additions & 1 deletion DragaliaAPI/Features/Reward/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public record Entity(
int Quantity = 1,
int? LimitBreakCount = null,
int? BuildupCount = null,
int? EquipableCount = null
int? EquipableCount = null,
bool? IsTemporary = false
// TODO: int? Level = null
)
{
Expand Down
6 changes: 3 additions & 3 deletions DragaliaAPI/Features/Reward/RewardService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public async Task<RewardGrantResult> GrantReward(Entity entity)
switch (entity.Type)
{
case EntityTypes.Chara:
return await RewardCharacter(entity);
return await RewardCharacter(entity, entity.IsTemporary ?? false);
case EntityTypes.Dragon:
for (int i = 0; i < entity.Quantity; i++)
await unitRepository.AddDragons((Dragons)entity.Id);
Expand Down Expand Up @@ -90,7 +90,7 @@ await inventoryRepository.GetMaterial((Materials)entity.Id)
return RewardGrantResult.Added;
}

private async Task<RewardGrantResult> RewardCharacter(Entity entity)
private async Task<RewardGrantResult> RewardCharacter(Entity entity, bool isTemporary)
{
if (entity.Type != EntityTypes.Chara)
throw new ArgumentException("Entity was not a character", nameof(entity));
Expand All @@ -109,7 +109,7 @@ private async Task<RewardGrantResult> RewardCharacter(Entity entity)
// TODO: Support EntityLevel/LimitBreak/etc here

logger.LogDebug("Granted new character entity: {@entity}", entity);
await unitRepository.AddCharas(chara);
await unitRepository.AddCharas(chara, isTemporary);
newEntities.Add(entity);
return RewardGrantResult.Added;
}
Expand Down
70 changes: 35 additions & 35 deletions DragaliaAPI/Services/Game/StoryService.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,40 @@
using System.Collections.Immutable;
using DragaliaAPI.Database.Entities;
using DragaliaAPI.Database.Repositories;
using DragaliaAPI.Features.Event;
using DragaliaAPI.Features.Fort;
using DragaliaAPI.Features.Missions;
using DragaliaAPI.Features.Reward;
using DragaliaAPI.Features.Shop;
using DragaliaAPI.Models.Generated;
using DragaliaAPI.Shared.Definitions.Enums;
using DragaliaAPI.Shared.MasterAsset;
using DragaliaAPI.Shared.MasterAsset.Models.Event;
using DragaliaAPI.Shared.MasterAsset.Models.Story;
using Microsoft.EntityFrameworkCore;

namespace DragaliaAPI.Services.Game;

public class StoryService : IStoryService
public class StoryService(
IStoryRepository storyRepository,
ILogger<StoryService> logger,
IUserDataRepository userDataRepository,
IInventoryRepository inventoryRepository,
ITutorialService tutorialService,
IFortRepository fortRepository,
IMissionProgressionService missionProgressionService,
IRewardService rewardService,
IPaymentService paymentService,
IEventService eventService,
IUnitRepository unitRepository
) : IStoryService
{
private const int DragonStoryWyrmite = 25;
private const int CastleStoryWyrmite = 50;
private const int CharaStoryWyrmite1 = 25;
private const int CharaStoryWyrmite2 = 10;
private const int QuestStoryWyrmite = 25;

private readonly IStoryRepository storyRepository;
private readonly ILogger<StoryService> logger;
private readonly IUserDataRepository userDataRepository;
private readonly IInventoryRepository inventoryRepository;
private readonly ITutorialService tutorialService;
private readonly IFortRepository fortRepository;
private readonly IMissionProgressionService missionProgressionService;
private readonly IRewardService rewardService;
private readonly IPaymentService paymentService;

public StoryService(
IStoryRepository storyRepository,
ILogger<StoryService> logger,
IUserDataRepository userDataRepository,
IInventoryRepository inventoryRepository,
ITutorialService tutorialService,
IFortRepository fortRepository,
IMissionProgressionService missionProgressionService,
IRewardService rewardService,
IPaymentService paymentService
)
{
this.storyRepository = storyRepository;
this.logger = logger;
this.userDataRepository = userDataRepository;
this.inventoryRepository = inventoryRepository;
this.tutorialService = tutorialService;
this.fortRepository = fortRepository;
this.missionProgressionService = missionProgressionService;
this.rewardService = rewardService;
this.paymentService = paymentService;
}

#region Eligibility check methods
public async Task<bool> CheckStoryEligibility(StoryTypes type, int storyId)
{
Expand Down Expand Up @@ -247,7 +228,26 @@ await rewardService.GrantReward(
}
}

logger.LogInformation("Granted rewards for reading new story: {rewards}", rewardList);
EventData? memoryEventData = await eventService.GetMemoryEventAssetData();
if (memoryEventData?.GuestJoinStoryId == storyId)
{
logger.LogDebug(
"Setting chara {id} to permanently owned",
memoryEventData.EventCharaId
);

await unitRepository.ClearIsTemporary(memoryEventData.EventCharaId);
rewardList.Add(
new AtgenBuildEventRewardEntityList()
{
entity_id = (int)memoryEventData.EventCharaId,
entity_quantity = 1,
entity_type = EntityTypes.Chara
}
);
}

logger.LogInformation("Granted rewards for reading new story: {@rewards}", rewardList);
return rewardList;
}

Expand Down

0 comments on commit 65086f9

Please sign in to comment.