Creating random "holidays" for a calendar

Please specify version and format if asking for help, or apply optional tags above:
Twine Version: 2.3.9
Story Format: Sugarcube 2.33.2

Using another thread I was able to create a basic calendaring system that is working nicely tracking the date and weekday/weekend. To add a bit of fictitious realism I wanted to have one random holiday day per month, with two months having static dates: with one in February; and two in December.

To prototype it, I’ve got everything in one passage. Once I’ve got it working it will be put into appropriate passages.

There may be a better way to do this, but this is what I was able to manage using the SugarCube documentation and my limited skills. Currently there is no weekday/weekend checking, that will be added once I get the below working.

I’ve got everything but two parts working:

  1. The created dates for the random months are not working. The month, max days in month, and created date all work, but when I try to put them into a date format they all display “1/1/2020, 0:00:00 AM”. The two static months work perfectly and the dates are valid. The only possible thing I can think of is that _months is a two-digit number and not a long month. Could that be it? If so, I’ll need to map that to a long month.
  2. The attempt to push the value to the array doesn’t seem to do anything. The second FOR just prints out ‘$holidays[_i]’ 13 times.

Any advice on what I’ve done wrong?

<<set _months to 1>>
<<set $holidays to []>>

<<for _months; _months <= 12; _months++>>
	<<if _months == 2>>\
		<<set _tempdate to new Date('February 14, 2020')>>\
		$holidays.push(_tempdate)
	<<elseif _months == 12>>\
		<<set _tempdate to new Date('December 25, 2020')>>\
		$holidays.push(_tempdate)
		<<set _tempdate to new Date('December 26, 2020')>>\
		$holidays.push("_tempdate")
	<<else>>\
		<!-- get number of days in month -->
		<<set _tempdate to new Date(2020, _months, 0).getDate()>>\
		<!-- get random date between 1 and max days in month -->
		<<set _temprandom to random(1, _tempdate)>>\
		<<set _tempdate to new Date('_months _temprandom, 2020')>>\
		$holidays.push("_tempdate")
	<</if>>\
<</for>>\

<<for _i = 0; _i <=13; _i++>>
	<<print _i + 1>>. $holidays[_i]
<</for>>

Thanks!

Edit: removed pointless lines in the two static month, setting the _temprandom value which wasn’t used.

You’re doing a couple of unnecessary and wrong things in your code.

First:

<<set _months to 1>>
...
<<for _months; _months <= 12; _months++>>

Since you’re setting _months to 1, then you should just do this:

<<for _months = 1; _months <= 12; _months++>>

Second, doing Date('_months _temprandom, 2020') won’t work, since you’re passing all of that as a string, thus the variables won’t get translated into their values. You should be doing Date(2020, _months, _temprandom) instead.

Third, you can’t do $holidays.push(_tempdate) or $holidays.push("_tempdate") without putting it inside of a <<set>>, <<run>>, or similar macro. Also, for $holidays.push("_tempdate") you’re making the same mistake as in the second problem, where you’re passing the parameter as a string, when you should be passing it as a value instead.

Fourth, you can get rid of all of the “\” bits by putting the code inside of a <<nobr>> macro.

Once we correct all of that (and compact some code) we get this:

<<nobr>>
	<<set $holidays to []>>
	<<for _months = 0; _months < 12; _months++>>
		<<if _months == 1>>
			<<set $holidays.push(new Date('February 14, 2020'))>>
		<<elseif _months == 11>>
			<<set $holidays.push(new Date('December 25, 2020'))>>
			<<set $holidays.push(new Date('December 26, 2020'))>>
		<<else>>
			/* Get number of days in month. */
			<<set _tempdate to new Date(2020, _months + 1, 0).getDate()>>
			<<set $holidays.push(new Date(2020, _months, random(1, _tempdate)))>>
		<</if>>
	<</for>>
<</nobr>>

Enjoy! :grinning:

EDIT: Fixed months being off by 1.

1 Like

Of course that makes perfect sense seeing it look so professional. I’m somewhat surprised I was able to get as close as I did on my first try. :wink: Well first 4-5 tries.

For the push, I think that is confusion on my part as I was following too literally the example here (http://www.motoslave.net/sugarcube/2/docs/#methods-array-prototype-method-push) where it showed:

// Given: $fruits = ["Apples", "Oranges"]
$fruits.push("Apples")  → Returns 3; $fruits ["Apples", "Oranges", "Apples"]

For some reason I assumed the lack of a ‘set’ in the push meant it wasn’t needed.

Thanks again!

I fixed the issue starting _1 at 1 as it skipped January. _i now starts at 0, so it includes January.

When I put that code into a passage and run it I get the below.

It’s a length is a length of 14, but there should be only 13.

There are a couple of other issues now:

  1. The array is now 14 elements long, which is one too many.
  2. February has two dates, the 14th (that should be there) and a random date. Shouldn’t the ‘if’ have skipped the random generation ‘else’?
  3. December has three dates now, the 25th/26th, and a random date. Shouldn’t the ‘if’ has also skipped the random generation ‘else’?
  4. Why did month 3 get missed?
1. 1/26/2020, 12:00:00 AM
2. 2/17/2020, 12:00:00 AM
3. 2/14/2020, 12:00:00 AM
4. 4/23/2020, 12:00:00 AM
5. 5/20/2020, 12:00:00 AM
6. 6/13/2020, 12:00:00 AM
7. 7/7/2020, 12:00:00 AM
8. 8/10/2020, 12:00:00 AM
9. 9/13/2020, 12:00:00 AM
10. 10/16/2020, 12:00:00 AM
11. 11/6/2020, 12:00:00 AM
12. 12/23/2020, 12:00:00 AM
13. 12/25/2020, 12:00:00 AM
14. 12/26/2020, 12:00:00 AM

Ah, right, the problem is that the months are 0 to 11, not 1 to 12. See the “monthIndex” parameter.

Simply reduce the months by 1. (I fixed the code I posted above.)

1 Like

Bah, of course. Something so simple. Thanks again!

Whoops, you’ll need this correction too:

<<set _tempdate to new Date(2020, _months + 1, 0).getDate()>>

since that gets the last day of the previous month.

1 Like