Giving User A Reward When Certain Amount of Time Has Passed - c#

During my game the user gets rewards every 10 minutes.
Even if they leave the app/game, when they come back, if 10 minutes has passed, they still get their reward.
So lets say for example: the user is playing and leaves the game with 5 minutes left until the next reward.
The user then leaves the game and returns an hour later.
How would I go about seeing if the 5 minutes have passed since the last open?
Does anyone know how to do this? I am using unity.

You may want to use DateTime struct, especially its DateTime.Now.
When your player leaves the game save the date time:
DateTime leaveDateTime = DateTime.Now;
//Store leaveDateTime value
When your player resumes,
//load leaveDateTime value
TimeSpan diff = DateTime.Now - leaveDateTime;
Then use your TimeSpan values (check TimeSpan.TotalMinutes) to give reward to your player.
if (TimeSpan.TotalMinutes >= 5){
//Give rewards for your players
}

Ian answer is OK but it has one problem, if user change the system (PC, mobile, ...) date and time, lets say add one year to the date, when he come back to game, he will get zillion reward unfairly! I think current dateTime must be recived from a ntp server instead of DateTime.Now.
Take a look at this answer : How to Query an NTP Server using C#?

Related

Convert time data to local time in C#

I've read a few posts about similar subjects but nothing seems to answer this question. My database has the following information about a time
Day of the week (a number between 0-6)
Time (a number of milliseconds since midnight in the users local time)
UTC offset ( number of hours different to UTC )
DST Observed (boolean stating if DST is observed in that time zone)
This data represents opening hours. So there is a time for each day. I want to display that time in the users local time making the assumption that each day is in the future
int dayOffset = availability.Day - (int)now.DayOfWeek
if (dayOffset < 0)
dayOffset += 7;
I'm really struggling to get my head around time zones and handling when one time zone might be observing DST while another maybe DOES observe DST but hasn't yet.
My main issue at the moment is I think I need to create a DateTimeOffset object for the non-local time but I'm not sure how to do that as I don't know if DST is in effect or not.
I hope I'm making myself clear. It really is a mind-bending experience working with dates and time!
As indicated by other answers, the usual solution to handling DateTime across time zones would be to store UTC times.
However, considering that you are not referencing an absolute time at a specific date, but instead are referring to a time at an infinite number of days in a specific time zone; storing the time as an UTC time doesn't make sense anymore, since the UTC time (even if we discard the date) would be different depending on the date, due to DST.
The best way to store the time is fairly close to what you have done already.
Your problem is that the time zone information you are storing at the moment is ambiguous, as it does not refer to a specific time zone, but instead refers to properties of the time zone.
To solve this problem, simply store the time zone identifier instead of the UTC offset and DST boolean.
It is now possible for us to construct the DateTime object and convert it to any time zone by using the TimeZoneInfo class:
int dayOffset = availability.Day - (int)DateTime.Today.DayOfWeek;
if (dayOffset < 0)
{
dayOffset += 7;
}
var openingHourStart = DateTime
.SpecifyKind(DateTime.Today, DateTimeKind.Unspecified)
.AddDays(dayOffset)
.AddMilliseconds(availability.Time);
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(availability.TimeZoneId);
var userTimeZone = TimeZoneInfo.Local;
var convertedOpeningHourStart = TimeZoneInfo.ConvertTime(openingHourStart,
sourceTimeZone,
userTimeZone);
Give a try to Quartz.NET.
It implements evaluation of CronExpressions, and even triggers to fire events at the given time. It can evaluate the next time an event will occur. This may help you out calculating the opening times.
Also, take a look at the cronmaker website: there you can understand the full potential of CronExpressions.
The CronExpressionDescriptor is a DotNET library for transforming CronExpressions into human readable strings.
Another library which I haven't tried yet is [HangFire].(https://www.hangfire.io/)
In this forum post you can find some discussion on how HangFire implements evaluation of RecurringJobs in local timezone with DST, which I believe is a solution for what you are looking for.
A comment to another answer made the problem a little bit more clear.
So, first and foremost, do store only UTC in your database. Really.
Now, since you are not interested in the actual dates, since you are storing working schedules that repeat weekly, the date only becomes relevant once you want to present your times - and when you put them in your database.
So let's first see how you get your times into your database correctly. I'm assuming a user will enter times in their own locale.
Make sure you first create a (localised) DateTime consisting of the current date and the given time (from the user), and transform that to a UTC DateTime (you can keep the current date, it doesn't matter):
var utcDateTime = DateTime.Now.Date
.AddHours(userHours)
.AddMinutes(userMinutes)
.ToUniversalTime();
Now when you are presenting these times to the user, simply go the other way:
var userDateTime = DateTime.Now.Date
.AddHours(utcDateTime.Hour)
.AddMinutes(utcDateTime.Minute)
.ToLocalTime();
And then you can use the userDateTime.Hour and .Minute for display purposes.
You should be leveraging DateTime.ToLocalTime() and TimeZoneInfo.ConvertTimeToUtc() in C# - see https://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime(v=vs.110).aspx.
If you want to store only times that you're open from Monday to Sunday, fine. Have a simple data table to describe only the time for each day (0 = Sunday through 7 = Saturday -- this is .Net's DayOfWeek enumeration). Your lookup table might look like:
0 null
1 08:00:00
2 08:00:00
3 08:00:00
4 08:30:00
5 08:30:00
6 10:30:00
(Use whatever data type works for you--SQL Server 2008+ has a TIME data type, for example. Null can be used for Closed on that day--i.e., no open time.)
When it comes time to display YOUR time to any other user, use must create your UTC time on-the-fly at the moment you are displaying information to the local user.
Conyc provided one approach. My approach uses simple date/time strings. To use my approach, just store time values per day in your database. Then you can look up the open time for any given day. To express that time for another user in any locale, use this code to convert your time to UTC (you can substitute the "08:00:00 AM" string value with a string variable that you populated after looking up the open time in your database):
var StoreOpenTimeInUtc = TimeZoneInfo.ConvertTimeToUtc(Convert.ToDateTime("08:00:00 AM"));
To look up the open time in your database for a particular day in the future, you will need to concatenate the date to your time value, like this:
var StoreOpenTimeInUtc = TimeZoneInfo.ConvertTimeToUtc(Convert.ToDateTime("04/28/2018 08:00:00 AM"));
Once you have an accurate StoreOpenTimeInUtc variable, you can use that as the UTC value on someone else's machine who is anywhere else on planet earth. To convert that UTC value to their local time, use the .NET ToLocalTime() method:
var OpenTimeForLocalUser = StoreOpenTimeInUtc.ToLocalTime();
Note that this approach requires you to store only the open times as shown above. You don't have to worry about dates, local offsets from UTC, or anything else. Just leverage ConvertTimeToUtc() and ToLocalTime() as shown.

Accelerated game time with TimeSpan in C#

I need to create an accelerated game time (presumably using a DispatcherTimer). I want 1 minute of 'real time' to equal 10 minutes of 'game time'.
Also, how would I set up gametime? Would this be a DateTime object? For example, let's say the game starts at 0600. Every 6 seconds I want the game time to increase by one minute.
How can I do this? Thanks!
GameTime is more likely to be a TimeSpan object which starts at zero and increments by as many seconds as you want by using its Add method. You would add 60 seconds to the TimeSpan object every time your "real world timer" registers a change of 6 seconds. Presumably you'd want to set your "real world timer" object up to notify you when each 6000ms has passed.

How to escape trial go-around with system time change?

Hi have an application offering a 30 days trial. When installed, I am adding a registry key with the current DateTime.Now value.
installDate = DateTime.Now;
RegistryKey regKeyAppRoot = Registry.CurrentUser.CreateSubKey(registryKeyPath);
regKeyAppRoot.SetValue("InstallDate", installDate);
Whenever the application is started, I load the value from the registry and compare it to the current DateTime.Now value again and obviously depending on the result of the comparison I show appropriate messages.
RegistryKey regKeyAppRoot = Registry.CurrentUser.CreateSubKey(registryKeyPath);
installDate = (DateTime)regKeyAppRoot.GetValue("InstallDate");
if (installDate.AddDays(30) > DateTime.Now)
; //MessageBox.Show(...)
My problem is that a simple change of the system time (to the past) would just allow the usage of the application again as the condition will no longer be met. That is explicable as the DateTime.Now property gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.
How can I escape that and get the exact number of days since when my application was installed?
You could save the date of the last check and compare the current date. If they are on different days, then increment a counter. In this way the user has "at most" 30 day uses.
So...
DateTime lastCheck = ... // Recover it from the registry
DateTime now = DateTime.Now.Date;
if (now != lastCheck.Date)
{
UsesCounter++;
}
lastCheck = now;
I'll add that normally it's a little better to use UtcNow, not Now, in this way you are safe from Daylight Time changes.
Another option is to use an Internet clock :-) There are many sites that give the exact time (this option is good only if your program normally connect to Internet)
One simple approach would be to save the date and time each time the program is started and quit. The next start compares the current date and time to the saved one. If it is less than the saved one, your application refuses to start.
This certainly wouldn't completely remove that problem, but it would make it harder for the user, because he would need to know what date and time he needs to set his computer to.
If you save time, when your application ended, you can check that current time is greater than ended time

C# date range within date range restricted by threshold x

I've asked a similar question before but this is more in depth given that I figured out could of things since then. So believe me it's not repeated.
My user will use the system to make a reservation of room space and provide a start date and an end date by which his reservation should expire. Now there is a threshold of x number of seats in the room. Many bookings could be placed on the same date range as long as the rooms are available.
What am finding difficulty dealing with is the multiple reservation on the same date, and even worst when it comes to booking a date range within a booked range. That is having a booking from 10oct example until 20, then another booking starting from let's say 11th oct till 30 or 5th nov. how can I keep track of this reservation? It's been killing me for the past few weeks.
I am using SQL database to store reservation form data and c# language of choice to develop asp application. Thanks in advance for the help.
Your bookings consist of two parts a start day and a duration. The booking exists for a set number of days for what I can tell. One way to standardize would be to convert all booking to a list of Jullian days that they exits on. This conversion is available in the Noda Time library and then you can utilize linqs set functions to see if a booking is overlapping. I am sure there are corner cases but that is how I would approach the problem

Does Daylightsaving time cause DateTime calculations to become negative

We are currently rewritting the core of our services, basically we have scheduled tasks that can run on intervals, dates, specific times etc etc etc.
Currently we're wondering if daylightsaving might cause trouble for us, basically we calculate the next possible runtime, based on what days the task should execute and between what times, and what interval. We do this by taking the current time, and adding days/minutes/hours to this DateTime.
We then take this new run time and subtract DateTime.Now from this DateTime, leaving us with the timespan untill the next run.
How ever, what if the current time is 01:50 on a daylightsavings day, we add 20 minutes, which is our set interval, and end up with a time of 02:10, how ever since this is daylightsavinds, it's actually 01:10.
When i subtract the current time (01:50) from the 01:10 (which is actually 02:10) does this return a negative value which i need to work around or does this never ever return a negative value because DateTime is just a long underneath holding the proper information?
Basically, the following code, is the check needed or not?
//Get interval between nextrun and right now!
double interval = (NextRun - DateTime.Now).TotalMilliseconds;
//Check if interval is ever less or equal to 0, should never happen but maybe with daylight saving time?
if(interval <= 0)
{
//Set default value
interval = IntervalInMilliseconds;
}
We believe that this check isn't needed but our googling so far hasn't given us a definative answer.
Use DateTime.UtcNow instead of DateTime.Now EVERYWHERE
First of all, you can try it yourself as it will help you understand how it works.
Essentially, using your example above, if you have 20 minutes to a local time, it would be 2:10 and not 1:10 as the computation is done in local time. If you want to get 1:10, you need to convert local time to universal time, add 20 minutes and then convert back to local time.
If you want real elapsed time, then you have to convert time to universal time before computing time difference. Also, if you work in local time, you won't be able to differentiate ambiguous time when the clock goes back.

Categories