I'm working on a project that needs to check the time difference from a first launch date. I'm using the NSDayCalendarUnit and NSWeekCalendarUnit. Basically for the first 2 weeks on every second day I want to perform something. The object I'm using needs to be in a certain state for each two days at a time.
So for example
Day 1 & 2, Week 0 - State 1
Day 3 & 4, Week 0 - State 2
...
Day 1 & 2, Week 1 - State 8
Day 3 & 4, Week 1 - State 9
Here is my code:
// get the data/time difference from the first launch
int daysDifferent = [[dateDifferenceInfo objectForKey:#"days"] intValue];
int weeksDifferent = [[dateDifferenceInfo objectForKey:#"weeks"] intValue];
if(daysDifferent == 2 | daysDifferent == 3 && !weeksDifferent && _dot.age != 2){
// set state
}
if(daysDifferent == 4 | daysDifferent == 5 && !weeksDifferent && _dot.age != 3){
// set state
}
if((daysDifferent == 6 && weeksDifferent == 0 | daysDifferent == 0 && weeksDifferent == 1) && _dot.age != 4){
// set state
}
if(daysDifferent == 0 | daysDifferent == 1 && weeksDifferent == 1 && _dot.age != 5){
// set state
}
if(daysDifferent == 2 | daysDifferent == 3 && weeksDifferent == 1 && _dot.age != 6){
// set state
}
if(daysDifferent == 4| daysDifferent == 5 && weeksDifferent == 1 && _dot.age != 7){
// set state
}
if((daysDifferent == 6 && weeksDifferent == 1 | daysDifferent == 0 && weeksDifferent == 2) && _dot.age != 8){
// set state
}
if(weeksDifferent >= 2 && !(daysDifferent % 2)){
// set state
}
Side note: I know it's bad code, I plan to replace this with switch cases, I just need to logic sorted first.
My question is is there a better way of calculating this kind of pattern?
I'm not totally clear on your goal, as you say:
for the first 2 weeks on every second day I want to perform something.
So for example
Day 1 & 2, Week 0 - State 1
Day 3 & 4, Week 0 - State 2
...
Day 1 & 2, Week 1 - State 8
Day 3 & 4, Week 1 - State 9
Where I would have thought it would be
Day 1 & 2, Week 0 - State 1
Day 3 & 4, Week 0 - State 2
Day 5 & 6, Week 0 - State 3
Day 7 Week 0 & Day 1 Week 1 - State 4.
...
So if your example is right, the calculation is different.
Based on the simpler example, I would calculate the time interval since the first date, and divide by twice the length of a day, taking the floor. That is the state:
NSDate *firstDate = ...
NSDate *secondDate = ...
NSTimeInterval interval = [ secondDate timeIntervalSinceDate: firstDate ];
double secondsPerDay = 60 * 60 * 24.0; // s per min times min per hr times hrs per dy.
int state = (int) (interval / secondsPerDay * 0.5 ) + 1;
If, on the other hand, it really is as you have described, the approach I would use as fast and simple would be to do a similar calculation - leaving out the 0.5 factor in the last line, and then use a simple table lookup to get the state from the day:
int table[ 14 ] = { 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8 };
int state = table[ (int) (interval / secondsPerDay ) ];
Related
How can I get the week number of the year by the model's time in Anylogic?
Thank for your help!
Simply call time(WEEK)
Returns the current model time in weeks.
If you need the relative week number of a year (0-51), you can use getDayOfYear(date()) / 52. and then round it how you like. getDayOfYear gives the relative day of a year for the current model time (0-364)
This is my code that returns the week number by the model's time (if the week starts on Monday):
int weekNumber = 1;
int dayOfWeekNewYear = 1;
if (getDayOfWeek(toDate(getYear(), 0, 1, 0, 0, 1)) == 1) {
dayOfWeekNewYear = 7;
}
else {
dayOfWeekNewYear = getDayOfWeek(toDate(getYear(), 0, 1, 0, 0, 1)) - 1;
}
if (dayOfWeekNewYear <= 4) {
weekNumber = (int)Math.ceil((double)(getDayOfYear(date()) + (dayOfWeekNewYear - 1))/7);
}
else {
if ((getDayOfYear(date()) - (8 - dayOfWeekNewYear)) > 0) {
weekNumber = (int)Math.ceil((double)(getDayOfYear(date()) - (8 - dayOfWeekNewYear))/7);
}
else {
weekNumber = 52;
}
}
Despite using isscalar, isinteger... the result after running is still true, I still had this test which is incorrect and in relation with Scalar values.
My program:
function valid = valid_date(year, month, day)
[y1 y2] = size(year);
[m1 m2] = size(month);
[d1 d2] = size(day);
if (mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0
is_leap_year = 1;
else
is_leap_year = 0;
end
if ~(y1==y2==d1==d2==m1==m2==1)
valid = false;
elseif any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31)
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif month == 2 && is_leap_year == 1
valid = (day >0 && day <=29);
elseif month == 2 && is_leap_year == 0
valid = (day >0 && day <=28);
else
valid = false;
end
end
The result after submitting my program, all tests are passed except the one related to scalar values:
Why did my program fail on the non-scalar test?
The way you're checking for scalars is really not well defined.
~(y1==y2==d1==d2==m1==m2==1)
This chained equivalence check is not the same as checking if all of your variables are equal to 1, consider the following counter-example:
1==0==0==1 % Output: 1
In this case none of your comparison variables should be 0, so you might skirt this issue, but it's still best to avoid it. You're also contending with floating point comparisons which are prone to issues.
You should use isscalar, you say you tried it but didn't show how. Something like this should work:
function valid = valid_date(year, month, day)
if ~( isscalar(year) && isscalar(month) && isscalar(day) )
valid = false;
return
end
% ... other code now we know inputs are scalar
end
Thank you so much #Wolfie. The problem is solved.
I used what you told me about and put it at the beginning of my function.
I show you guys the code, in case you had the same error:
function valid = valid_date(year, month, day)
if ~(isscalar(year) && isscalar(month) && isscalar(day))
valid = false;
return
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
is_leap_year = 1;
else
is_leap_year = 0;
end
if any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31);
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif (month == 2 && is_leap_year == 1)
valid = (day >0 && day <=29);
elseif (month == 2 && is_leap_year == 0)
valid = (day >0 && day <=28);
else
valid = false;
end
end
Yaaay all the tests are passed lhamdullah!
The following code is working. But the 2nd doesnt work. Why ?
specificTime = dayofweek == dayofweek.monday and hour == 0 and minute == 0 and second == 0
countbar = barssince(specificTime)
plot(countbar)
The following code doesn't work. I don't know why. Please help.
specificTime = dayofweek == dayofweek.sunday and hour == 23 and minute == 59 and second == 59
countbar = barssince(specificTime)
plot(countbar)
And I'd like to ask how to get the number of bars from last Sunday (I mean Sunday[1]) and previous Sunday (Sunday[2]). Thanks for your help.
I haven't been programming very long, so I'm practicing some logic exercises in dlang. Any ideas on what I've done wrong here. When I get to a leap year, my program just keeps looping on the WHILE.
import std.stdio;
void main()
{
bool dead;
string thing;
int phew = 5; //days
int tahr = 1; //months
int tron; //monthsDate
string[7] days = ["Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"];
int date = 28;
string[12] months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
int year = 1996;
int hours = 11;
int mins = 28;
string ampm = "pm";
bool ly;
int leap = 1996;
int cen = 996;
//writeln("This program is incomplete. Obviously.");
write("Press Enter to Continue.");
readf("%s\n",&thing);
while(!dead)
{
while(hours <= 12)
{
while(mins <= 59)
{
if(mins < 10)
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":0",mins,ampm,": ");
else
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":",mins,ampm,": ");
readf("%s\n",&thing);
mins++;
}
hours++;
if(hours == 12 && ampm == "am")
{
ampm = "pm";
}
else if (hours == 12 && ampm == "pm")
{
ampm = "am";
phew++;
date++;
if(phew > 6)
phew = 0;
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(date == 31 && (tahr == 1 || tahr == 3 || tahr == 5 || tahr == 8 || tahr == 10))
{
date = 1;
tahr++;
}
else if (tahr == 11 && date == 32)
{
tahr = 0;
date = 1;
year++;
cen++;
if(cen == 1000)
{
writeln("Happy Millennium!");
cen = 0;
}
else
writeln("Happy New Year!");
}
else if(date == 32 && (tahr == 0 || tahr == 2 || tahr == 4 || tahr == 6 || tahr == 7 || tahr == 9))
{
date = 1;
tahr++;
}
}
if(hours == 13)
{
hours = 1;
}
mins = 0;
}
}
}
The important part is this:
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)///
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap=-4;
}
}
So, I figured out the issue almost immediately after posting. Basically, I wrote =+ instead of +=. Very simple mistake. That's what I get for typing too fast. So, I've fixed up the code now, if you have any other suggestions, make sure to put them in the comments. Thanks.
Decided to print out leap into the terminal, and I figured out my issue. Leap was continuously equal to 4, because I wrote =+ instead of +=. It was just a case of clicking the wrong button first. That's what I get for typing fast. The program works now, as far as I know. Feel free to correct me on anything else you may notice.
I haven't read it in depth, but I recommend you add lots of debug writelns.
Particularly just inside the block you're THINKING should get run:
if((date == 29 || date == 30) && tahr == 1) {
writefln("Handling leap years...");
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
writefln("In loop, Leap <= year? %s", leap <= year);
This will allow you to debug more what is actually happening when your program is run.
I have a set of checks to perform certain tasks.
// tempDouble is a (double), hour is an int
if (tempDouble > 60.0 && (hour >= 6 || hour <= 17)) { //CLEAR
NSLog(#"CLEAR");
}
else if (tempDouble > 60.0 && (hour < 6 || hour > 17)) { //NIGHT_CLEAR
NSLog(#"NIGHT_CLEAR");
}
else if (tempDouble <= 60.0 && (hour >= 6 || hour <= 17)) { //CLOUDY
NSLog(#"CLOUDY");
}
else if (tempDouble > 60.0 && (hour < 6 || hour > 17)) { //NIGHT_CLOUDY
NSLog(#"NIGHT_CLOUDY");
}
When I have a temp of 76.3 and an hour of 2, for example, I'd expect it to jump to NIGHT_CLEAR, but it actually goes to CLEAR. Did I set up my comparisons wrongly?
Thanks in advance for this simple question!
(hour >= 6 || hour <= 17)
is always true. All real numbers are either greater than or equal to 6 or less than or equal to 17 (some are both). I think you want:
(hour >= 6 && hour <= 17)
The same also applies to CLOUDY.
Some of your ||'s might be better off being &&'s.
Perhaps what you want is...
if (tempDouble > 60.0 && (hour >= 6 && hour <= 17)) { //CLEAR
NSLog(#"CLEAR");
}
else if (tempDouble > 60.0 && (hour < 6 && hour > 17)) { //NIGHT_CLEAR
NSLog(#"NIGHT_CLEAR");
}
else if (tempDouble <= 60.0 && (hour >= 6 || hour <= 17)) { //CLOUDY
NSLog(#"CLOUDY");
}
else if (tempDouble > 60.0 && (hour < 6 || hour > 17)) { //NIGHT_CLOUDY
NSLog(#"NIGHT_CLOUDY");
}