Okay. I played with the day-night and managed to get one to do seasonal…
But then Marilu wanted … more. So much more. So more she will have. I present a seasonal profile (and some debugging text to remove once you’re happy with it). Maybe it could help with Sinder Park’s changes or who knows. 
// =====================
// 1️⃣ JSON type definitions
// =====================
@json
class HolidayEntry {
key!: string;
value!: string;
}
@json
class HolidayRange {
name!: string;
startMonth!: i32;
startDay!: i32;
endMonth!: i32;
endDay!: i32;
}
@json
class Season {
name!: string;
startMonth!: i32;
startDay!: i32;
endMonth!: i32;
endDay!: i32;
}
@json
class CalendarData {
holidays!: HolidayEntry[];
holidayRanges!: HolidayRange[];
seasons!: Season[];
}
// =====================
// 2️⃣ Embedded JSON data
// =====================
const calendarDataText = `
{
"holidays": [
{ "key": "1-1", "value": "new-years-day" },
{ "key": "2-14", "value": "valentines-day" },
{ "key": "10-31", "value": "halloween-day" },
{ "key": "12-25", "value": "christmas-day" }
],
"holidayRanges": [
{ "name": "halloween", "startMonth": 10, "startDay": 1, "endMonth": 10, "endDay": 31 },
{ "name": "wonderland", "startMonth": 12, "startDay": 20, "endMonth": 12, "endDay": 31 }
],
"seasons": [
{ "name": "winter", "startMonth": 12, "startDay": 21, "endMonth": 3, "endDay": 19 },
{ "name": "spring", "startMonth": 3, "startDay": 20, "endMonth": 6, "endDay": 20 },
{ "name": "summer", "startMonth": 6, "startDay": 21, "endMonth": 9, "endDay": 21 },
{ "name": "autumn", "startMonth": 9, "startDay": 22, "endMonth": 12, "endDay": 20 }
]
}
`;
// =====================
// 3️⃣ Global state
// =====================
let data: CalendarData | null = null;
let holidayMap: Map<string, string> = new Map();
// =====================
// 4️⃣ Logic helpers
// =====================
function isDateInRange(month: i32, day: i32, startM: i32, startD: i32, endM: i32, endD: i32): bool {
if (startM == endM) return month == startM && day >= startD && day <= endD;
if (month > startM && month < endM) return true;
if (month == startM && day >= startD) return true;
if (month == endM && day <= endD) return true;
return false;
}
function getCalendarEvent(month: i32, day: i32): string {
if (data == null) return "an unknown time";
const d = changetype<CalendarData>(data);
const key = `${month}-${day}`;
Room.describe(`Date: ${key}`);
if (holidayMap.has(key)) {
const single = holidayMap.get(key);
if (single) return single;
}
for (let i = 0; i < d.holidayRanges.length; i++) {
const hr = d.holidayRanges[i];
if (isDateInRange(month, day, hr.startMonth, hr.startDay, hr.endMonth, hr.endDay)) {
return hr.name;
}
}
for (let i = 0; i < d.seasons.length; i++) {
const s = d.seasons[i];
if (isDateInRange(month, day, s.startMonth, s.startDay, s.endMonth, s.endDay)) {
return s.name;
}
}
return "an ordinary day";
}
// =====================
// 5️⃣ Lifecycle
// =====================
export function onActivate(): void {
if (data == null) {
data = changetype<CalendarData>(JSON.parse<CalendarData>(calendarDataText));
// Build map
const d = changetype<CalendarData>(data);
holidayMap = new Map<string, string>();
for (let i = 0; i < d.holidays.length; i++) {
const h = d.holidays[i];
holidayMap.set(h.key, h.value);
}
Room.describe(
`[Calendar] Loaded ${holidayMap.size.toString()} holidays, ` +
`${d.holidayRanges.length.toString()} holiday ranges, and ` +
`${d.seasons.length.toString()} seasons.`
);
}
const now = new Date(Date.now());
const month = now.getUTCMonth() + 1;
const day = now.getUTCDate();
const result = getCalendarEvent(month, day);
Room.describe(`You step into the room on ${result}.`);
Room.useProfile(result);
const msUntil = scheduleNextUpdate(now);
const hours = (msUntil / (1000 * 60 * 60)).toString();
Room.describe(`[Calendar] Next update scheduled in ${hours} hours.`);
}
export function onMessage(addr: string, topic: string, dataMsg: string | null, sender: string): void {
if (topic == "change") {
onActivate();
}
}
// =====================
// 6️⃣ Scheduler
// =====================
function scheduleNextUpdate(now: Date): i64 {
const nextMidnight = Date.UTC(
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate() + 1,
0, 0, 0
);
const msUntil = nextMidnight - now.getTime();
Script.post("#", "change", null, msUntil);
return msUntil;
}