Fix job boards
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using Prospect.Server.Api.Services.CloudScript.Models.Data;
|
||||||
|
|
||||||
namespace Prospect.Server.Api.Models.Data;
|
namespace Prospect.Server.Api.Models.Data;
|
||||||
|
|
||||||
@@ -13,3 +14,12 @@ public class PlayerBalance
|
|||||||
[JsonPropertyName("IN")]
|
[JsonPropertyName("IN")]
|
||||||
public int InsuranceTokens { get; set; }
|
public int InsuranceTokens { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class JobBoardsData
|
||||||
|
{
|
||||||
|
[JsonPropertyName("lastBoardRefreshTimeUtc")]
|
||||||
|
public FYTimestamp LastBoardRefreshTimeUtc { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("boards")]
|
||||||
|
public List<FYFactionContractsData> Boards { get; set; }
|
||||||
|
}
|
||||||
@@ -50,6 +50,8 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
private readonly UserDataService _userDataService;
|
private readonly UserDataService _userDataService;
|
||||||
private readonly TitleDataService _titleDataService;
|
private readonly TitleDataService _titleDataService;
|
||||||
|
private readonly string[] difficulties = ["Easy", "Medium", "Hard"];
|
||||||
|
private readonly Random rnd = new Random();
|
||||||
|
|
||||||
public ClaimActiveContract(IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService)
|
public ClaimActiveContract(IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService)
|
||||||
{
|
{
|
||||||
@@ -66,11 +68,10 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
throw new CloudScriptException("CloudScript was not called within a http request");
|
throw new CloudScriptException("CloudScript was not called within a http request");
|
||||||
}
|
}
|
||||||
var userId = context.User.FindAuthUserId();
|
var userId = context.User.FindAuthUserId();
|
||||||
var titleData = _titleDataService.Find(new List<string>{"Contracts", "Blueprints"});
|
var titleData = _titleDataService.Find(new List<string>{ "Contracts", "Blueprints", "Jobs", "LevelData" });
|
||||||
|
|
||||||
var contracts = JsonSerializer.Deserialize<Dictionary<string, TitleDataContractInfo>>(titleData["Contracts"]);
|
var contracts = JsonSerializer.Deserialize<Dictionary<string, TitleDataContractInfo>>(titleData["Contracts"]);
|
||||||
var contract = contracts[request.ContractID];
|
if (!contracts.TryGetValue(request.ContractID, out var contract)) {
|
||||||
if (contract == null) {
|
|
||||||
return new FYClaimCompletedActiveContractRewardsResult
|
return new FYClaimCompletedActiveContractRewardsResult
|
||||||
{
|
{
|
||||||
UserID = userId,
|
UserID = userId,
|
||||||
@@ -82,16 +83,17 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
var factionKey = "FactionProgression" + contract.Faction;
|
var factionKey = "FactionProgression" + contract.Faction;
|
||||||
var userData = await _userDataService.FindAsync(
|
var userData = await _userDataService.FindAsync(
|
||||||
userId, userId,
|
userId, userId,
|
||||||
new List<string>{"ContractsActive", "ContractsOneTimeCompleted", "Balance", "Inventory", factionKey}
|
new List<string>{"ContractsActive", "ContractsOneTimeCompleted", "Balance", "Inventory", factionKey, "JobBoardsData" }
|
||||||
);
|
);
|
||||||
|
|
||||||
var factionProgression = JsonSerializer.Deserialize<int>(userData[factionKey].Value);
|
var factionProgression = JsonSerializer.Deserialize<int>(userData[factionKey].Value);
|
||||||
var contractsActive = JsonSerializer.Deserialize<FYGetActiveContractsResult>(userData["ContractsActive"].Value);
|
var contractsActive = JsonSerializer.Deserialize<FYGetActiveContractsResult>(userData["ContractsActive"].Value);
|
||||||
var contractsCompleted = JsonSerializer.Deserialize<FYGetCompletedContractsResult>(userData["ContractsOneTimeCompleted"].Value);
|
var contractsCompleted = JsonSerializer.Deserialize<FYGetCompletedContractsResult>(userData["ContractsOneTimeCompleted"].Value);
|
||||||
|
var jobBoardsData = JsonSerializer.Deserialize<JobBoardsData>(userData["JobBoardsData"].Value);
|
||||||
var balance = JsonSerializer.Deserialize<PlayerBalance>(userData["Balance"].Value);
|
var balance = JsonSerializer.Deserialize<PlayerBalance>(userData["Balance"].Value);
|
||||||
var inventory = JsonSerializer.Deserialize<List<FYCustomItemInfo>>(userData["Inventory"].Value);
|
var inventory = JsonSerializer.Deserialize<List<FYCustomItemInfo>>(userData["Inventory"].Value);
|
||||||
|
|
||||||
var targetContractIdx = contractsActive.Contracts.FindIndex(item => item.ContractID == request.ContractID);
|
var targetContractIdx = contractsActive.Contracts.FindIndex(item => item.ContractID == contract.Name);
|
||||||
if (targetContractIdx == -1) {
|
if (targetContractIdx == -1) {
|
||||||
return new FYClaimCompletedActiveContractRewardsResult
|
return new FYClaimCompletedActiveContractRewardsResult
|
||||||
{
|
{
|
||||||
@@ -106,6 +108,7 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
var targetContract = contractsActive.Contracts[targetContractIdx];
|
var targetContract = contractsActive.Contracts[targetContractIdx];
|
||||||
List<FYCustomItemInfo> itemsUpdatedOrRemoved = [];
|
List<FYCustomItemInfo> itemsUpdatedOrRemoved = [];
|
||||||
HashSet<string> deletedItemsIds = [];
|
HashSet<string> deletedItemsIds = [];
|
||||||
|
// TODO: Optimize
|
||||||
for (var i = 0; i < contract.Objectives.Length; i++) {
|
for (var i = 0; i < contract.Objectives.Length; i++) {
|
||||||
var objective = contract.Objectives[i];
|
var objective = contract.Objectives[i];
|
||||||
int remaining = objective.MaxProgress;
|
int remaining = objective.MaxProgress;
|
||||||
@@ -211,10 +214,33 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
factionProgression += contract.ReputationIncrease;
|
factionProgression += contract.ReputationIncrease;
|
||||||
contractsActive.Contracts.RemoveAt(targetContractIdx);
|
contractsActive.Contracts.RemoveAt(targetContractIdx);
|
||||||
// Main contracts can be completed only once.
|
// Main contracts can be completed only once.
|
||||||
|
// Other contracts should be jobs.
|
||||||
|
var newContractIdOnBoard = "";
|
||||||
if (contract.IsMainContract) {
|
if (contract.IsMainContract) {
|
||||||
contractsCompleted.ContractsIDs.Add(request.ContractID);
|
contractsCompleted.ContractsIDs.Add(contract.Name);
|
||||||
|
} else {
|
||||||
|
var parts = contract.Name.Split('-');
|
||||||
|
var difficulty = parts[1];
|
||||||
|
|
||||||
|
var levelsData = JsonSerializer.Deserialize<Dictionary<string, int[]>>(titleData["LevelData"]);
|
||||||
|
var levels = levelsData[contract.Faction];
|
||||||
|
var jobs = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string[]>>>(titleData["Jobs"]);
|
||||||
|
var level = levels.Length - Array.FindIndex(levels, (int xp) => {
|
||||||
|
return factionProgression >= xp;
|
||||||
|
});
|
||||||
|
|
||||||
|
var factionBoard = jobBoardsData.Boards.Find(c => c.FactionId == contract.Faction);
|
||||||
|
var idx = Array.FindIndex(difficulties, d => d == difficulty);
|
||||||
|
var factionJobs = jobs[contract.Faction];
|
||||||
|
var jobsAvailable = Array.FindAll(factionJobs[difficulty], (string jobId) => {
|
||||||
|
return level >= contracts[jobId].UnlockData.Level;
|
||||||
|
});
|
||||||
|
// If player completes a job, it means he has at least one unlocked anyway.
|
||||||
|
newContractIdOnBoard = jobsAvailable[rnd.Next(jobsAvailable.Length)];
|
||||||
|
factionBoard.Contracts[idx].ContractId = newContractIdOnBoard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Check for next unlock in contracts instead of relying on client
|
||||||
var newContracts = new List<FYActiveContractPlayerData>();
|
var newContracts = new List<FYActiveContractPlayerData>();
|
||||||
foreach (var contractIdToUnlock in request.ContractsToUnlock) {
|
foreach (var contractIdToUnlock in request.ContractsToUnlock) {
|
||||||
var contractToUnlock = contracts[contractIdToUnlock];
|
var contractToUnlock = contracts[contractIdToUnlock];
|
||||||
@@ -235,6 +261,7 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
["Balance"] = JsonSerializer.Serialize(balance),
|
["Balance"] = JsonSerializer.Serialize(balance),
|
||||||
["Inventory"] = JsonSerializer.Serialize(newInventory),
|
["Inventory"] = JsonSerializer.Serialize(newInventory),
|
||||||
[factionKey] = JsonSerializer.Serialize(factionProgression),
|
[factionKey] = JsonSerializer.Serialize(factionProgression),
|
||||||
|
["JobBoardsData"] = JsonSerializer.Serialize(jobBoardsData),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -242,12 +269,12 @@ public class ClaimActiveContract : ICloudScriptFunction<FYClaimCompletedActiveCo
|
|||||||
{
|
{
|
||||||
UserID = userId,
|
UserID = userId,
|
||||||
Error = "",
|
Error = "",
|
||||||
ClaimedContractID = request.ContractID,
|
ClaimedContractID = contract.Name,
|
||||||
ContractsActivated = newContracts,
|
ContractsActivated = newContracts,
|
||||||
ItemsUpdatedOrRemoved = itemsUpdatedOrRemoved,
|
ItemsUpdatedOrRemoved = itemsUpdatedOrRemoved,
|
||||||
ChangedCurrencies = changedCurrencies.ToArray(),
|
ChangedCurrencies = changedCurrencies.ToArray(),
|
||||||
ItemsGranted = itemsGranted,
|
ItemsGranted = itemsGranted,
|
||||||
NewContractIdOnBoard = "", // TODO: This should be a replacement contract apparently?
|
NewContractIdOnBoard = newContractIdOnBoard,
|
||||||
PlayerFactionProgressData = new FYPlayerFactionProgressData {
|
PlayerFactionProgressData = new FYPlayerFactionProgressData {
|
||||||
FactionID = contract.Faction,
|
FactionID = contract.Faction,
|
||||||
CurrentProgression = factionProgression,
|
CurrentProgression = factionProgression,
|
||||||
|
|||||||
+71
-70
@@ -1,4 +1,7 @@
|
|||||||
using System.Text.Json;
|
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.Auth.Extensions;
|
||||||
using Prospect.Server.Api.Services.CloudScript.Models;
|
using Prospect.Server.Api.Services.CloudScript.Models;
|
||||||
using Prospect.Server.Api.Services.CloudScript.Models.Data;
|
using Prospect.Server.Api.Services.CloudScript.Models.Data;
|
||||||
@@ -11,11 +14,16 @@ public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction<FYQuery
|
|||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
private readonly UserDataService _userDataService;
|
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)
|
public RequestActiveObjectivesAndBoardsData(IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService)
|
||||||
{
|
{
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
_userDataService = userDataService;
|
_userDataService = userDataService;
|
||||||
|
_titleDataService = titleDataService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<FYGetPlayerContractsResult> ExecuteAsync(FYQueryFactionProgressionRequest request)
|
public async Task<FYGetPlayerContractsResult> ExecuteAsync(FYQueryFactionProgressionRequest request)
|
||||||
@@ -26,10 +34,65 @@ public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction<FYQuery
|
|||||||
return new FYGetPlayerContractsResult{};
|
return new FYGetPlayerContractsResult{};
|
||||||
}
|
}
|
||||||
var userId = context.User.FindAuthUserId();
|
var userId = context.User.FindAuthUserId();
|
||||||
var userData = await _userDataService.FindAsync(userId, userId, new List<string>{"ContractsActive"});
|
|
||||||
var contractsActive = JsonSerializer.Deserialize<FYGetActiveContractsResult>(userData["ContractsActive"].Value);
|
|
||||||
|
|
||||||
// TODO: Get player's contract boards and refresh
|
var userData = await _userDataService.FindAsync(userId, userId, new List<string>{ "ContractsActive", "JobBoardsData", "FactionProgressionKorolev", "FactionProgressionICA", "FactionProgressionOsiris" });
|
||||||
|
var contractsActive = JsonSerializer.Deserialize<FYGetActiveContractsResult>(userData["ContractsActive"].Value);
|
||||||
|
var jobBoardsData = JsonSerializer.Deserialize<JobBoardsData>(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<string> { "Contracts", "Jobs", "LevelData" });
|
||||||
|
|
||||||
|
var contracts = JsonSerializer.Deserialize<Dictionary<string, TitleDataContractInfo>>(titleData["Contracts"]);
|
||||||
|
var jobs = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string[]>>>(titleData["Jobs"]);
|
||||||
|
var levelsData = JsonSerializer.Deserialize<Dictionary<string, int[]>>(titleData["LevelData"]);
|
||||||
|
var currentQuests = new Dictionary<string, Dictionary<string, bool>> {
|
||||||
|
["Korolev"] = new Dictionary<string, bool> { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false },
|
||||||
|
["Osiris"] = new Dictionary<string, bool> { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false },
|
||||||
|
["ICA"] = new Dictionary<string, bool> { ["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<int>(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<string, string> { ["JobBoardsData"] = JsonSerializer.Serialize(jobBoardsData) }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return new FYGetPlayerContractsResult
|
return new FYGetPlayerContractsResult
|
||||||
{
|
{
|
||||||
@@ -38,72 +101,10 @@ public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction<FYQuery
|
|||||||
ActiveContracts = contractsActive.Contracts,
|
ActiveContracts = contractsActive.Contracts,
|
||||||
FactionsContracts = new FYFactionsContractsData
|
FactionsContracts = new FYFactionsContractsData
|
||||||
{
|
{
|
||||||
Boards = new List<FYFactionContractsData>
|
Boards = boards,
|
||||||
{
|
LastBoardRefreshTimeUtc = lastBoardRefreshTimeUtc
|
||||||
new FYFactionContractsData
|
|
||||||
{
|
|
||||||
FactionId = "ICA",
|
|
||||||
Contracts = new List<FYFactionContractData>
|
|
||||||
{
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Easy-ICA-Gather-1",
|
|
||||||
},
|
},
|
||||||
new FYFactionContractData
|
RefreshHours24UtcFromBackend = 12 // Doesn't seem to work
|
||||||
{
|
|
||||||
ContractId = "NEW-Medium-ICA-Uplink-1",
|
|
||||||
},
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Hard-ICA-Uplink-1",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new FYFactionContractsData
|
|
||||||
{
|
|
||||||
FactionId = "Korolev",
|
|
||||||
Contracts = new List<FYFactionContractData>
|
|
||||||
{
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Easy-KOR-Mine-4",
|
|
||||||
},
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Medium-KOR-Mine-1",
|
|
||||||
},
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Hard-KOR-PvP-6",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new FYFactionContractsData
|
|
||||||
{
|
|
||||||
FactionId = "Osiris",
|
|
||||||
Contracts = new List<FYFactionContractData>
|
|
||||||
{
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Easy-Osiris-Brightcaps-1",
|
|
||||||
},
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Medium-Osiris-Gather-1",
|
|
||||||
},
|
|
||||||
new FYFactionContractData
|
|
||||||
{
|
|
||||||
ContractId = "NEW-Hard-Osiris-Gather-7",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LastBoardRefreshTimeUtc = new FYTimestamp
|
|
||||||
{
|
|
||||||
Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RefreshHours24UtcFromBackend = 12
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user