question

robert avatar image
robert asked

Cycling Daily/Weekly/Monthly events, best practices with statistics

I’m looking for the best pratice for following situation.

In our game we offer Daily, Weekly and Monthly Events. An event has one or more levels to choose from. For example, the Daily Event lets you play Level1, Level7 or Level12, just for today. The next day, the levels in the Daily Event will cycle and there might be Level4, Level8, Level15 then.

For each level in each event the user will get prizes when the event has finished time-wise and is about to cycle. Lets say, 1000 coins for Level1, 5000 coins for Level7 and 10000 coins for Level12 in the daily event and lets say 20.000 coins for Level1 in the weekly event.

So, we had a pretty naive approach and came up with following solution:

We create 3 scheduled tasks. CycleDaily runs every day, CycleWeekly runs every week, CycleMonthly runs every month. Each scheduled task calls an appropriate cloud script function which cycles the events and updates the title data. The title data holds the entire Live Events configuration which gets queried by the client. We also add the time when the events expire to the title data so that the client can show a nice “Event running until xxxxxx” badge.

This all works pretty fine, but now the problematical part: statistics.

Whenever we cycle an event we have to reset/increment statistics associated with the event/level so that the prize table is run through and players a gifted accordingly.

As there is no Server API this looks like to be impossible. We could set a reset time on the statistics itself, but we have no clue about the timing effect for this. E.g. daily reset for statistic + scheduled task running at 00:00 everyday to cycle the event. I think it might happen that either the task runs before the statistics are reset or vice versa. We could set the scheduled task to run at 00:05, but, yeah…

Second, creating the statistics. We have up to 9 levels, split into x events. Additionally Level1 can be for example in DailyEvents at first position and also in DailyEvents at second position. For this we would need 2 (y) different statistics (e.g. DailyEvent/Level7/Slot1). So, we sum up to 9 * x * y. Additionally, we have no way to set reset time on statistics from the Server API. Whenever we cycle the events or create new events or levels or change the level position in the event there is always the possibility to one “forgets” to correctly configure the automatically created statistics.

We then though about making it “simpler”. Using statistics in the form “EventName/LevelSlot”, e.g. when we have three levels live in DailyEvents:

DailyEvent/Level4 will use DailyEvent_1 as statistic value, DailyEvent/Level8 will use DailyEvent_2 and DailyEvent/Level15 will use DailyEvent_3. (The next day DailyEvent/Level7 will "reuse" DailyEvent_1, and so on...) This would greatly reduce the amount of required statistics and we can pre-create them manually, but the risk for the timing difference between statistics reset and event cycle is even bigger then, if suddenly a new level is writing into the statistics used for another level earlier.

Additionally it appears there is no way to read the PrizeTable either from Server API and Client API to display it to the user (which means we need to keep a copy of the prizetable in the title data).

Hope you get what I mean and hope about any ideas how to handle this.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

Well first, it sounds like you want to give prizes to more than just the first 1,000 players in the leaderboard, in which case you wouldn't be using Prize Tables anyway (they're limited to 1,000 prize table ranks). So really, what you want is to define the prizes internally and then use a scheduled task to process the players.

Basically:

Use player segmentation to track on player activity. You'll want to have one for each time period - daily, weekly, monthly. Define the segment so that only players who have logged in within that period are processed.

Put the prize info in the Cloud Script directly, as static data. That way, there's no wait on the call to read Title Data.

I'd also put the metadata for the event (start/stop times, etc.) in the static Cloud Script data, so that you can use it to control which statistic you write to/read from, and to return it from there to the player.

In the script you run from the scheduled task, check the player's score, grant the appropriate prize, then set their score to 0.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

robert avatar image
robert answered

We got a good working solution implemented already.

As we reward the top 10 players only we just use a simple ranked_on_leaderboard rule. In the associated cloudscript method we query the title data and reward the user accordingly. (custom reward item written to players inventory with custom data describing rewards, e.g. money, items, etc...)

We don't use player segments as a player can be part of X events in Y time periods at the same time. This would add a lot of segments to keep track of and also introduces more timing relevant problems when events switch.

Regarding the leaderboards, we now use "fixed" leaderboards in the form of "DailyEvents1, DailyEvents2, etc..." and associate them with the real event using Title Data. (No more leaderboards per level but per scheduled time period and event index)

We shuffle all events using a scheduled task running each hour. This scheduled task manually checks if the event time expired and will shuffle the levels for each event then. The scheduled task runs 5 minutes after every hour to make sure the leaderboard reset settled and all rewards are sent out. (Eat event in the client is locked for this 5 minutes with a nice "Evaluation results message").


Thanks

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.