From 06ce4ac69551f9f0f6731d0957b9badd085cd7f2 Mon Sep 17 00:00:00 2001 From: Sainan Date: Tue, 25 Mar 2025 15:11:26 -0700 Subject: [PATCH] chore: more faithful handling of daily tribute (#1324) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1324 --- src/controllers/api/loginRewardsController.ts | 29 +++++++++++++------ .../api/loginRewardsSelectionController.ts | 2 +- src/models/loginModel.ts | 2 +- src/services/loginRewardService.ts | 18 ++++++++++-- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/controllers/api/loginRewardsController.ts b/src/controllers/api/loginRewardsController.ts index f6430e28..16d77261 100644 --- a/src/controllers/api/loginRewardsController.ts +++ b/src/controllers/api/loginRewardsController.ts @@ -1,31 +1,42 @@ import { RequestHandler } from "express"; import { getAccountForRequest } from "@/src/services/loginService"; -import { claimLoginReward, getRandomLoginRewards, ILoginRewardsReponse } from "@/src/services/loginRewardService"; +import { + claimLoginReward, + getRandomLoginRewards, + ILoginRewardsReponse, + isLoginRewardAChoice +} from "@/src/services/loginRewardService"; import { getInventory } from "@/src/services/inventoryService"; export const loginRewardsController: RequestHandler = async (req, res) => { const account = await getAccountForRequest(req); const today = Math.trunc(Date.now() / 86400000) * 86400; + const isMilestoneDay = account.LoginDays == 5 || account.LoginDays % 50 == 0; + const nextMilestoneDay = account.LoginDays < 5 ? 5 : (Math.trunc(account.LoginDays / 50) + 1) * 50; if (today == account.LastLoginRewardDate) { - res.end(); + res.json({ + DailyTributeInfo: { + IsMilestoneDay: isMilestoneDay, + IsChooseRewardSet: isLoginRewardAChoice(account), + LoginDays: account.LoginDays, + NextMilestoneReward: "", + NextMilestoneDay: nextMilestoneDay + } + } satisfies ILoginRewardsReponse); return; } - account.LoginDays += 1; - account.LastLoginRewardDate = today; - await account.save(); const inventory = await getInventory(account._id.toString()); const randomRewards = getRandomLoginRewards(account, inventory); - const isMilestoneDay = account.LoginDays == 5 || account.LoginDays % 50 == 0; const response: ILoginRewardsReponse = { DailyTributeInfo: { Rewards: randomRewards, IsMilestoneDay: isMilestoneDay, IsChooseRewardSet: randomRewards.length != 1, LoginDays: account.LoginDays, - //NextMilestoneReward: "", - NextMilestoneDay: account.LoginDays < 5 ? 5 : (Math.trunc(account.LoginDays / 50) + 1) * 50, + NextMilestoneReward: "", + NextMilestoneDay: nextMilestoneDay, HasChosenReward: false }, LastLoginRewardDate: today @@ -33,7 +44,7 @@ export const loginRewardsController: RequestHandler = async (req, res) => { if (!isMilestoneDay && randomRewards.length == 1) { response.DailyTributeInfo.HasChosenReward = true; response.DailyTributeInfo.ChosenReward = randomRewards[0]; - response.DailyTributeInfo.NewInventory = await claimLoginReward(inventory, randomRewards[0]); + response.DailyTributeInfo.NewInventory = await claimLoginReward(account, inventory, randomRewards[0]); await inventory.save(); } res.json(response); diff --git a/src/controllers/api/loginRewardsSelectionController.ts b/src/controllers/api/loginRewardsSelectionController.ts index b1ebc9a6..8bd14dd7 100644 --- a/src/controllers/api/loginRewardsSelectionController.ts +++ b/src/controllers/api/loginRewardsSelectionController.ts @@ -28,7 +28,7 @@ export const loginRewardsSelectionController: RequestHandler = async (req, res) } else { const randomRewards = getRandomLoginRewards(account, inventory); chosenReward = randomRewards.find(x => x.StoreItemType == body.ChosenReward)!; - inventoryChanges = await claimLoginReward(inventory, chosenReward); + inventoryChanges = await claimLoginReward(account, inventory, chosenReward); } await inventory.save(); res.json({ diff --git a/src/models/loginModel.ts b/src/models/loginModel.ts index 2218a27d..7b12c07a 100644 --- a/src/models/loginModel.ts +++ b/src/models/loginModel.ts @@ -23,7 +23,7 @@ const databaseAccountSchema = new Schema( Dropped: Boolean, LatestEventMessageDate: { type: Date, default: 0 }, LastLoginRewardDate: { type: Number, default: 0 }, - LoginDays: { type: Number, default: 0 } + LoginDays: { type: Number, default: 1 } }, opts ); diff --git a/src/services/loginRewardService.ts b/src/services/loginRewardService.ts index 4d5c562a..5e7c442e 100644 --- a/src/services/loginRewardService.ts +++ b/src/services/loginRewardService.ts @@ -14,7 +14,7 @@ export interface ILoginRewardsReponse { IsMilestoneDay?: boolean; IsChooseRewardSet?: boolean; LoginDays?: number; // when calling multiple times per day, this is already incremented to represent "tomorrow" - //NextMilestoneReward?: ""; + NextMilestoneReward?: ""; NextMilestoneDay?: number; // seems to not be used if IsMilestoneDay HasChosenReward?: boolean; NewInventory?: IInventoryChanges; @@ -46,6 +46,13 @@ const scaleAmount = (day: number, amount: number, scalingMultiplier: number): nu return amount + Math.min(day, 3000) / divisor; }; +// Always produces the same result for the same account _id & LoginDays pair. +export const isLoginRewardAChoice = (account: TAccountDocument): boolean => { + const accountSeed = parseInt(account._id.toString().substring(16), 16); + const rng = new CRng(mixSeeds(accountSeed, account.LoginDays)); + return rng.random() < 0.25; // Using 25% as an approximate chance for pick-a-doors. More conclusive data analysis is needed. +}; + // Always produces the same result for the same account _id & LoginDays pair. export const getRandomLoginRewards = ( account: TAccountDocument, @@ -53,9 +60,9 @@ export const getRandomLoginRewards = ( ): ILoginReward[] => { const accountSeed = parseInt(account._id.toString().substring(16), 16); const rng = new CRng(mixSeeds(accountSeed, account.LoginDays)); + const pick_a_door = rng.random() < 0.25; // Using 25% as an approximate chance for pick-a-doors. More conclusive data analysis is needed. const rewards = [getRandomLoginReward(rng, account.LoginDays, inventory)]; - // Using 25% an approximate chance for pick-a-doors. More conclusive data analysis is needed. - if (rng.random() < 0.25) { + if (pick_a_door) { do { const reward = getRandomLoginReward(rng, account.LoginDays, inventory); if (!rewards.find(x => x.StoreItemType == reward.StoreItemType)) { @@ -114,9 +121,14 @@ const getRandomLoginReward = (rng: CRng, day: number, inventory: TInventoryDatab }; export const claimLoginReward = async ( + account: TAccountDocument, inventory: TInventoryDatabaseDocument, reward: ILoginReward ): Promise => { + account.LoginDays += 1; + account.LastLoginRewardDate = Math.trunc(Date.now() / 86400000) * 86400; + await account.save(); + switch (reward.RewardType) { case "RT_RESOURCE": case "RT_STORE_ITEM":