using System.Collections; using System.Diagnostics.Contracts; using System.Text.Json; using Prospect.Server.Api.Models.Data; using Prospect.Server.Api.Services.Auth.Extensions; using Prospect.Server.Api.Services.CloudScript.Models; using Prospect.Server.Api.Services.CloudScript.Models.Data; using Prospect.Server.Api.Services.UserData; namespace Prospect.Server.Api.Services.CloudScript.Functions; [CloudScriptFunction("RequestActiveObjectivesAndBoardsData")] public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction { private readonly IHttpContextAccessor _httpContextAccessor; private readonly UserDataService _userDataService; private readonly TitleDataService _titleDataService; private readonly string[] factions = ["Korolev", "Osiris", "ICA"]; // TODO: Order is important private readonly string[] difficulties = ["Easy", "Medium", "Hard"]; private readonly Random rnd = new Random(); public RequestActiveObjectivesAndBoardsData(IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService) { _httpContextAccessor = httpContextAccessor; _userDataService = userDataService; _titleDataService = titleDataService; } public async Task ExecuteAsync(FYQueryFactionProgressionRequest request) { var context = _httpContextAccessor.HttpContext; if (context == null) { return new FYGetPlayerContractsResult{}; } var userId = context.User.FindAuthUserId(); var userData = await _userDataService.FindAsync(userId, userId, new List{ "ContractsActive", "JobBoardsData", "FactionProgressionKorolev", "FactionProgressionICA", "FactionProgressionOsiris" }); var contractsActive = JsonSerializer.Deserialize(userData["ContractsActive"].Value); var jobBoardsData = JsonSerializer.Deserialize(userData["JobBoardsData"].Value); var now = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var lastBoardRefreshTimeUtc = jobBoardsData.LastBoardRefreshTimeUtc; var boards = jobBoardsData.Boards; // The boards are updated once in 3 hours if (now >= lastBoardRefreshTimeUtc.Seconds + 60 * 60 * 3) { var titleData = _titleDataService.Find(new List { "Contracts", "Jobs", "LevelData" }); var contracts = JsonSerializer.Deserialize>(titleData["Contracts"]); var jobs = JsonSerializer.Deserialize>>(titleData["Jobs"]); var levelsData = JsonSerializer.Deserialize>(titleData["LevelData"]); var currentQuests = new Dictionary> { ["Korolev"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, ["Osiris"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, ["ICA"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, }; foreach (var contract in contractsActive.Contracts) { var parts = contract.ContractID.Split('-'); if (parts[0] != "NEW") { continue; } var difficulty = parts[1]; var faction = parts[2] == "KOR" ? "Korolev" : parts[2]; currentQuests[faction][difficulty] = true; } for (var i = 0; i < factions.Length; i++) { var faction = factions[i]; var factionProgression = JsonSerializer.Deserialize(userData[$"FactionProgression{faction}"].Value); var levels = levelsData[faction]; var level = levels.Length - Array.FindIndex(levels, (int xp) => { return factionProgression >= xp; }); for (var j = 0; j < difficulties.Length; j++) { var difficulty = difficulties[j]; if (currentQuests[faction][difficulty]) { continue; } var factionJobs = jobs[faction]; var jobsAvailable = Array.FindAll(factionJobs[difficulty], (string jobId) => { return level >= contracts[jobId].UnlockData.Level; }); string jobId = jobsAvailable.Length > 0 ? jobsAvailable[rnd.Next(jobsAvailable.Length)] : factionJobs[difficulty][0]; boards[i].Contracts[j] = new FYFactionContractData { ContractId = jobId }; } } lastBoardRefreshTimeUtc.Seconds = now; await _userDataService.UpdateAsync( userId, userId, new Dictionary { ["JobBoardsData"] = JsonSerializer.Serialize(jobBoardsData) } ); } return new FYGetPlayerContractsResult { UserId = userId, Error = null, ActiveContracts = contractsActive.Contracts, FactionsContracts = new FYFactionsContractsData { Boards = boards, LastBoardRefreshTimeUtc = lastBoardRefreshTimeUtc }, RefreshHours24UtcFromBackend = 12 // Doesn't seem to work }; } }