chore: more faithful handling of daily tribute
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build / build (18) (push) Successful in 1m3s
				
			
		
			
				
	
				Build / build (20) (push) Successful in 1m15s
				
			
		
			
				
	
				Build / build (22) (push) Successful in 1m15s
				
			
		
			
				
	
				Build / build (18) (pull_request) Successful in 59s
				
			
		
			
				
	
				Build / build (20) (pull_request) Successful in 1m14s
				
			
		
			
				
	
				Build / build (22) (pull_request) Successful in 1m18s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build / build (18) (push) Successful in 1m3s
				
			Build / build (20) (push) Successful in 1m15s
				
			Build / build (22) (push) Successful in 1m15s
				
			Build / build (18) (pull_request) Successful in 59s
				
			Build / build (20) (pull_request) Successful in 1m14s
				
			Build / build (22) (pull_request) Successful in 1m18s
				
			This commit is contained in:
		
							parent
							
								
									2ec2b0278a
								
							
						
					
					
						commit
						24765c44b2
					
				@ -1,31 +1,42 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
					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";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
					export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
    const today = Math.trunc(Date.now() / 86400000) * 86400;
 | 
					    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) {
 | 
					    if (today == account.LastLoginRewardDate) {
 | 
				
			||||||
        res.end();
 | 
					        res.json({
 | 
				
			||||||
 | 
					            DailyTributeInfo: {
 | 
				
			||||||
 | 
					                IsMilestoneDay: isMilestoneDay,
 | 
				
			||||||
 | 
					                IsChooseRewardSet: isLoginRewardAChoice(account),
 | 
				
			||||||
 | 
					                LoginDays: account.LoginDays,
 | 
				
			||||||
 | 
					                NextMilestoneReward: "",
 | 
				
			||||||
 | 
					                NextMilestoneDay: nextMilestoneDay
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } satisfies ILoginRewardsReponse);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    account.LoginDays += 1;
 | 
					 | 
				
			||||||
    account.LastLoginRewardDate = today;
 | 
					 | 
				
			||||||
    await account.save();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const inventory = await getInventory(account._id.toString());
 | 
					    const inventory = await getInventory(account._id.toString());
 | 
				
			||||||
    const randomRewards = getRandomLoginRewards(account, inventory);
 | 
					    const randomRewards = getRandomLoginRewards(account, inventory);
 | 
				
			||||||
    const isMilestoneDay = account.LoginDays == 5 || account.LoginDays % 50 == 0;
 | 
					 | 
				
			||||||
    const response: ILoginRewardsReponse = {
 | 
					    const response: ILoginRewardsReponse = {
 | 
				
			||||||
        DailyTributeInfo: {
 | 
					        DailyTributeInfo: {
 | 
				
			||||||
            Rewards: randomRewards,
 | 
					            Rewards: randomRewards,
 | 
				
			||||||
            IsMilestoneDay: isMilestoneDay,
 | 
					            IsMilestoneDay: isMilestoneDay,
 | 
				
			||||||
            IsChooseRewardSet: randomRewards.length != 1,
 | 
					            IsChooseRewardSet: randomRewards.length != 1,
 | 
				
			||||||
            LoginDays: account.LoginDays,
 | 
					            LoginDays: account.LoginDays,
 | 
				
			||||||
            //NextMilestoneReward: "",
 | 
					            NextMilestoneReward: "",
 | 
				
			||||||
            NextMilestoneDay: account.LoginDays < 5 ? 5 : (Math.trunc(account.LoginDays / 50) + 1) * 50,
 | 
					            NextMilestoneDay: nextMilestoneDay,
 | 
				
			||||||
            HasChosenReward: false
 | 
					            HasChosenReward: false
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        LastLoginRewardDate: today
 | 
					        LastLoginRewardDate: today
 | 
				
			||||||
@ -33,7 +44,7 @@ export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
    if (!isMilestoneDay && randomRewards.length == 1) {
 | 
					    if (!isMilestoneDay && randomRewards.length == 1) {
 | 
				
			||||||
        response.DailyTributeInfo.HasChosenReward = true;
 | 
					        response.DailyTributeInfo.HasChosenReward = true;
 | 
				
			||||||
        response.DailyTributeInfo.ChosenReward = randomRewards[0];
 | 
					        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();
 | 
					        await inventory.save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    res.json(response);
 | 
					    res.json(response);
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ export const loginRewardsSelectionController: RequestHandler = async (req, res)
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        const randomRewards = getRandomLoginRewards(account, inventory);
 | 
					        const randomRewards = getRandomLoginRewards(account, inventory);
 | 
				
			||||||
        chosenReward = randomRewards.find(x => x.StoreItemType == body.ChosenReward)!;
 | 
					        chosenReward = randomRewards.find(x => x.StoreItemType == body.ChosenReward)!;
 | 
				
			||||||
        inventoryChanges = await claimLoginReward(inventory, chosenReward);
 | 
					        inventoryChanges = await claimLoginReward(account, inventory, chosenReward);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await inventory.save();
 | 
					    await inventory.save();
 | 
				
			||||||
    res.json({
 | 
					    res.json({
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
 | 
				
			|||||||
        Dropped: Boolean,
 | 
					        Dropped: Boolean,
 | 
				
			||||||
        LatestEventMessageDate: { type: Date, default: 0 },
 | 
					        LatestEventMessageDate: { type: Date, default: 0 },
 | 
				
			||||||
        LastLoginRewardDate: { type: Number, default: 0 },
 | 
					        LastLoginRewardDate: { type: Number, default: 0 },
 | 
				
			||||||
        LoginDays: { type: Number, default: 0 }
 | 
					        LoginDays: { type: Number, default: 1 }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    opts
 | 
					    opts
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ export interface ILoginRewardsReponse {
 | 
				
			|||||||
        IsMilestoneDay?: boolean;
 | 
					        IsMilestoneDay?: boolean;
 | 
				
			||||||
        IsChooseRewardSet?: boolean;
 | 
					        IsChooseRewardSet?: boolean;
 | 
				
			||||||
        LoginDays?: number; // when calling multiple times per day, this is already incremented to represent "tomorrow"
 | 
					        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
 | 
					        NextMilestoneDay?: number; // seems to not be used if IsMilestoneDay
 | 
				
			||||||
        HasChosenReward?: boolean;
 | 
					        HasChosenReward?: boolean;
 | 
				
			||||||
        NewInventory?: IInventoryChanges;
 | 
					        NewInventory?: IInventoryChanges;
 | 
				
			||||||
@ -46,6 +46,13 @@ const scaleAmount = (day: number, amount: number, scalingMultiplier: number): nu
 | 
				
			|||||||
    return amount + Math.min(day, 3000) / divisor;
 | 
					    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.
 | 
					// Always produces the same result for the same account _id & LoginDays pair.
 | 
				
			||||||
export const getRandomLoginRewards = (
 | 
					export const getRandomLoginRewards = (
 | 
				
			||||||
    account: TAccountDocument,
 | 
					    account: TAccountDocument,
 | 
				
			||||||
@ -53,9 +60,9 @@ export const getRandomLoginRewards = (
 | 
				
			|||||||
): ILoginReward[] => {
 | 
					): ILoginReward[] => {
 | 
				
			||||||
    const accountSeed = parseInt(account._id.toString().substring(16), 16);
 | 
					    const accountSeed = parseInt(account._id.toString().substring(16), 16);
 | 
				
			||||||
    const rng = new CRng(mixSeeds(accountSeed, account.LoginDays));
 | 
					    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)];
 | 
					    const rewards = [getRandomLoginReward(rng, account.LoginDays, inventory)];
 | 
				
			||||||
    // Using 25% an approximate chance for pick-a-doors. More conclusive data analysis is needed.
 | 
					    if (pick_a_door) {
 | 
				
			||||||
    if (rng.random() < 0.25) {
 | 
					 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
            const reward = getRandomLoginReward(rng, account.LoginDays, inventory);
 | 
					            const reward = getRandomLoginReward(rng, account.LoginDays, inventory);
 | 
				
			||||||
            if (!rewards.find(x => x.StoreItemType == reward.StoreItemType)) {
 | 
					            if (!rewards.find(x => x.StoreItemType == reward.StoreItemType)) {
 | 
				
			||||||
@ -114,9 +121,14 @@ const getRandomLoginReward = (rng: CRng, day: number, inventory: TInventoryDatab
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const claimLoginReward = async (
 | 
					export const claimLoginReward = async (
 | 
				
			||||||
 | 
					    account: TAccountDocument,
 | 
				
			||||||
    inventory: TInventoryDatabaseDocument,
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
    reward: ILoginReward
 | 
					    reward: ILoginReward
 | 
				
			||||||
): Promise<IInventoryChanges> => {
 | 
					): Promise<IInventoryChanges> => {
 | 
				
			||||||
 | 
					    account.LoginDays += 1;
 | 
				
			||||||
 | 
					    account.LastLoginRewardDate = Math.trunc(Date.now() / 86400000) * 86400;
 | 
				
			||||||
 | 
					    await account.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (reward.RewardType) {
 | 
					    switch (reward.RewardType) {
 | 
				
			||||||
        case "RT_RESOURCE":
 | 
					        case "RT_RESOURCE":
 | 
				
			||||||
        case "RT_STORE_ITEM":
 | 
					        case "RT_STORE_ITEM":
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user