From 2a9d851918ebbfbc536066a2dfe54ee9f6415b2f Mon Sep 17 00:00:00 2001 From: Rob Harbaugh Date: Wed, 5 Nov 2025 19:59:37 -0500 Subject: [PATCH] initial proper of seasons --- .gitignore | 23 +++ LICENSE | 21 ++ README.md | 7 + src/builder.c | 505 +++++++++++++++++++++++++++++++++++++++++++++++ src/builder.h | 10 + src/church_day.c | 81 ++++++++ src/church_day.h | 57 ++++++ src/main.c | 26 +++ 8 files changed, 730 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/builder.c create mode 100644 src/builder.h create mode 100644 src/church_day.c create mode 100644 src/church_day.h create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8dff11 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Compiled output +calendarium +*.o +*.out +*.exe + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f4affa8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Rob Harbaugh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..856730c --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# calendarium +Calculate the church calendar for the current year. + +Right now, when you run it, you get a printout of every day for your current calendar year. +This is opinionated - it's the current USCCB calendar at first. + +Eventually there'll be args for specific days, including readings and stuff. diff --git a/src/builder.c b/src/builder.c new file mode 100644 index 0000000..209cd9a --- /dev/null +++ b/src/builder.c @@ -0,0 +1,505 @@ +#include "builder.h" +#include +#include +#include + +//helper to add days to a date +static struct tm add_days(struct tm date, int days) { + date.tm_mday += days; + mktime(&date); + return date; +} + +//helper to compare dates (return negative if d1 < d2, 0 if equal, positive if d1 > d2) +static int compare_dates(struct tm d1, struct tm d2) { + if (d1.tm_year != d2.tm_year) return d1.tm_year - d2.tm_year; + if (d1.tm_mon != d2.tm_mon) return d1.tm_mon - d2.tm_mon; + return d1.tm_mday - d2.tm_mday; +} + +/// Computus algorithm to calculate Easter Sunday +static ChurchDay easter_for_year(int year) { + int a = year % 19; + int b = year / 100; + int c = year % 100; + int d = b / 4; + int e = b % 4; + int f = (b + 8) / 25; + int g = (b - f + 1) / 3; + int h = (19 * a + b - d - g + 15) % 30; + int i = c / 4; + int k = c % 4; + int l = (32 + 2 * e + 2 * i - h - k) % 7; + int m = (a + 11 * h + 22 * l) / 451; + int month = (h + l - 7 * m + 114) / 31; + int day = (h + l - 7 * m + 114) % 31 + 1; + + return church_day_new(year, month, day, SOLEMNITY, EASTER, + "Easter Sunday of the Resurrection of the Lord"); +} + +static ChurchDay ash_wednesday(const ChurchDay *easter) { + struct tm date = add_days(easter->date, -46); + ChurchDay cd; + cd.date = date; + cd.class = SOLEMNITY; + cd.season = LENT; + strcpy(cd.description, "Ash Wednesday"); + return cd; +} + +static ChurchDay first_sunday_advent(int year) { + struct tm dec_first = {0}; + dec_first.tm_year = year - 1900; + dec_first.tm_mon = 11; // December + dec_first.tm_mday = 1; + mktime(&dec_first); + + int days_to_subtract; + switch (dec_first.tm_wday) { + case 0: days_to_subtract = 0; break; // Sunday + case 1: days_to_subtract = 1; break; // Monday + case 2: days_to_subtract = 2; break; // Tuesday + case 3: days_to_subtract = 3; break; // Wednesday + case 4: days_to_subtract = 4; break; // Thursday + case 5: days_to_subtract = -2; break; // Friday + case 6: days_to_subtract = -1; break; // Saturday + default: days_to_subtract = 0; break; + } + + struct tm date = add_days(dec_first, -days_to_subtract); + ChurchDay cd; + cd.date = date; + cd.class = SUNDAY; + cd.season = ADVENT; + strcpy(cd.description, "1st Sunday of Advent"); + return cd; +} + +static ChurchDay epiphany(int year) { + for (int day = 2; day <= 8; day++) { + struct tm date = {0}; + date.tm_year = year - 1900; + date.tm_mon = 0; // January + date.tm_mday = day; + mktime(&date); + + if (date.tm_wday == 0) { // Sunday + return church_day_new(year, 1, day, SOLEMNITY, CHRISTMAS, + "The Epiphany of the Lord"); + } + } + // Fallback (shouldn't happen) + return church_day_new(year, 1, 6, SOLEMNITY, CHRISTMAS, "The Epiphany of the Lord"); +} + +static ChurchDay baptism(ChurchDay epiphany_day) { + struct tm date = add_days(epiphany_day.date, 7); + ChurchDay cd; + cd.date = date; + cd.class = FEAST; + cd.season = CHRISTMAS; + strcpy(cd.description, "The Baptism of the Lord"); + return cd; +} + +static ChurchDay pentecost(ChurchDay easter) { + struct tm date = add_days(easter.date, 49); + ChurchDay cd; + cd.date = date; + cd.class = SOLEMNITY; + cd.season = EASTER; + strcpy(cd.description, "Pentecost Sunday"); + return cd; +} + +static const char* ordinal_suffix(int number) { + char str[16]; + snprintf(str, sizeof(str), "%d", number); + + if (strstr(str, "11") == str + strlen(str) - 2 || + strstr(str, "12") == str + strlen(str) - 2 || + strstr(str, "13") == str + strlen(str) - 2) { + return "th"; + } + + switch (str[strlen(str) - 1]) { + case '1': return "st"; + case '2': return "nd"; + case '3': return "rd"; + default: return "th"; + } +} + +static const char* day_string(int wday) { + switch (wday) { + case 0: return "Sunday"; + case 1: return "Monday"; + case 2: return "Tuesday"; + case 3: return "Wednesday"; + case 4: return "Thursday"; + case 5: return "Friday"; + case 6: return "Saturday"; + default: return "Unknown"; + } +} + +static void calculate_advent(ChurchYear *cy, const ChurchDay *start) { + ChurchDay current = *start; + int sunday_counter = 1; + + church_year_add(cy, current); + + while (1) { + if (current.date.tm_mon == 11 && current.date.tm_mday == 24) { + break; + } + + current.date = add_days(current.date, 1); + + if (current.date.tm_wday == 0) { + sunday_counter++; + } + + current.season = ADVENT; + current.class = (current.date.tm_wday == 0) ? SUNDAY : SEASONAL_WEEKDAY; + + if (current.date.tm_mday >= 17 && current.date.tm_mon == 11) { + snprintf(current.description, sizeof(current.description), + "December %d%s", current.date.tm_mday, + ordinal_suffix(current.date.tm_mday)); + } else if (current.date.tm_wday == 0) { + snprintf(current.description, sizeof(current.description), + "%d%s Sunday of Advent", sunday_counter, + ordinal_suffix(sunday_counter)); + } else { + snprintf(current.description, sizeof(current.description), + "%s of the %d%s week of Advent", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + } + + church_year_add(cy, current); + } +} + +static void calculate_christmas(ChurchYear *cy, int year) { + ChurchDay epiphany_day = epiphany(year + 1); + ChurchDay baptism_day = baptism(epiphany_day); + + ChurchDay christmas = church_day_new(year, 12, 25, SOLEMNITY, CHRISTMAS, + "The Nativity of the Lord (Christmas)"); + church_year_add(cy, christmas); + + ChurchDay current = christmas; + while (1) { + struct tm next_date = add_days(current.date, 1); + if (next_date.tm_mon == epiphany_day.date.tm_mon && + next_date.tm_mday == epiphany_day.date.tm_mday) { + break; + } + + current.date = next_date; + current.season = CHRISTMAS; + current.class = (current.date.tm_wday == 0) ? FEAST : SEASONAL_WEEKDAY; + + if (current.date.tm_wday == 0) { + strcpy(current.description, "The Holy Family of Jesus, Mary, and Joseph"); + } else { + switch (current.date.tm_mday) { + case 26: strcpy(current.description, "Saint Stephen, First Martyr"); break; + case 27: strcpy(current.description, "Saint John, Apostle and Evangelist"); break; + case 28: strcpy(current.description, "Holy Innocents"); break; + case 29: strcpy(current.description, "Fifth Day within the Octave of the Nativity of the Lord"); break; + case 30: strcpy(current.description, "Sixth Day within the Octave of the Nativity of the Lord"); break; + case 31: strcpy(current.description, "Seventh Day within the Octave of the Nativity of the Lord"); break; + default: strcpy(current.description, "Christmas Weekday"); break; + } + } + + church_year_add(cy, current); + } + + church_year_add(cy, epiphany_day); + + current = epiphany_day; + while (1) { + struct tm next_date = add_days(current.date, 1); + if (next_date.tm_mon == baptism_day.date.tm_mon && + next_date.tm_mday == baptism_day.date.tm_mday) { + break; + } + + current.date = next_date; + current.season = CHRISTMAS; + current.class = SEASONAL_WEEKDAY; + snprintf(current.description, sizeof(current.description), + "%s between Epiphany and Baptism of the Lord", + day_string(current.date.tm_wday)); + + church_year_add(cy, current); + } + + church_year_add(cy, baptism_day); +} + +static void calculate_lent(ChurchYear *cy, ChurchDay ash_wed) { + ChurchDay easter = easter_for_year(ash_wed.date.tm_year + 1900); + struct tm stop_date = add_days(easter.date, -8); + + ChurchDay current = ash_wed; + int sunday_counter = 0; + + church_year_add(cy, current); + + while (compare_dates(current.date, stop_date) != 0) { + current.date = add_days(current.date, 1); + + if (current.date.tm_wday == 0) { + sunday_counter++; + } + + current.season = LENT; + current.class = (current.date.tm_wday == 0) ? SUNDAY : SEASONAL_WEEKDAY; + + if (sunday_counter == 0) { + snprintf(current.description, sizeof(current.description), + "%s after Ash Wednesday", day_string(current.date.tm_wday)); + } else if (current.date.tm_wday == 0) { + snprintf(current.description, sizeof(current.description), + "%d%s Sunday of Lent", sunday_counter, + ordinal_suffix(sunday_counter)); + } else { + snprintf(current.description, sizeof(current.description), + "%s of the %d%s week of Lent", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + } + + church_year_add(cy, current); + } +} + +static void calculate_easter(ChurchYear *cy, ChurchDay sat_before) { + ChurchDay easter = easter_for_year(sat_before.date.tm_year + 1900); + struct tm ps_date = add_days(easter.date, -7); + + ChurchDay palm_sunday; + palm_sunday.date = ps_date; + palm_sunday.class = SUNDAY; + palm_sunday.season = LENT; + strcpy(palm_sunday.description, "Palm Sunday of the Passion of the Lord"); + church_year_add(cy, palm_sunday); + + const char* holy_week_names[] = { + "", + "Monday of Holy Week", + "Tuesday of Holy Week", + "Wednesday of Holy Week", + "Holy Thursday", + "Friday of the Passion of the Lord", + "Holy Saturday" + }; + + for (int days_after = 1; days_after <= 6; days_after++) { + ChurchDay day; + day.date = add_days(ps_date, days_after); + day.class = (days_after < 4) ? SEASONAL_WEEKDAY : SOLEMNITY; + day.season = (days_after < 4) ? LENT : TRIDUUM; + strcpy(day.description, holy_week_names[days_after]); + church_year_add(cy, day); + } + + church_year_add(cy, easter); + + const char* octave_names[] = { + "", + "Monday within the Octave of Easter", + "Tuesday within the Octave of Easter", + "Wednesday within the Octave of Easter", + "Thursday within the Octave of Easter", + "Friday within the Octave of Easter", + "Saturday within the Octave of Easter", + "Sunday of Divine Mercy" + }; + + for (int octave_days = 1; octave_days <= 7; octave_days++) { + ChurchDay day; + day.date = add_days(easter.date, octave_days); + day.class = SOLEMNITY; + day.season = EASTER; + strcpy(day.description, octave_names[octave_days]); + church_year_add(cy, day); + } + + ChurchDay pentecost_day = pentecost(easter); + struct tm stop_date = add_days(pentecost_day.date, -1); + + ChurchDay current = cy->days[cy->count - 1]; + int sunday_counter = 2; + + while (compare_dates(current.date, stop_date) != 0) { + current.date = add_days(current.date, 1); + + if (current.date.tm_wday == 0) { + sunday_counter++; + } + + current.season = EASTER; + current.class = (current.date.tm_wday == 0) ? SUNDAY : SEASONAL_WEEKDAY; + + if (current.date.tm_wday == 0) { + if (sunday_counter == 7) { + strcpy(current.description, "The Ascension of the Lord"); + } else { + snprintf(current.description, sizeof(current.description), + "%d%s Sunday of Easter", sunday_counter, + ordinal_suffix(sunday_counter)); + } + } else { + snprintf(current.description, sizeof(current.description), + "%s of the %d%s week of Easter", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + } + + church_year_add(cy, current); + } + + church_year_add(cy, pentecost_day); +} + +static void calculate_otime_prelent(ChurchYear *cy, ChurchDay baptism_day) { + ChurchDay easter = easter_for_year(baptism_day.date.tm_year + 1900); + ChurchDay ash_wed = ash_wednesday(&easter); + struct tm stop_date = add_days(ash_wed.date, -1); + + ChurchDay current; + current.date = add_days(baptism_day.date, 1); + current.class = FERIAL_WEEKDAY; + current.season = ORDINARY_TIME; + strcpy(current.description, "Monday of the 1st week in Ordinary Time"); + + int sunday_counter = 1; + church_year_add(cy, current); + + while (compare_dates(current.date, stop_date) != 0) { + current.date = add_days(current.date, 1); + + if (current.date.tm_wday == 0) { + sunday_counter++; + } + + current.season = ORDINARY_TIME; + current.class = (current.date.tm_wday == 0) ? SUNDAY : FERIAL_WEEKDAY; + + if (current.date.tm_wday == 0) { + snprintf(current.description, sizeof(current.description), + "%d%s Sunday of Ordinary Time", sunday_counter, + ordinal_suffix(sunday_counter)); + } else { + snprintf(current.description, sizeof(current.description), + "%s of the %d%s week of Ordinary Time", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + } + + church_year_add(cy, current); + } +} + +static void calculate_otime_posteaster(ChurchYear *cy, ChurchDay pentecost_day) { + ChurchDay first_advent = first_sunday_advent(pentecost_day.date.tm_year + 1900); + struct tm last_day = add_days(first_advent.date, -1); + + struct tm trinity_sunday = add_days(pentecost_day.date, 7); + struct tm corpus_christi = add_days(trinity_sunday, 7); + + // Build backwards + ChurchDay *temp_days = malloc(366 * sizeof(ChurchDay)); + size_t temp_count = 0; + + ChurchDay current; + current.date = last_day; + current.class = FERIAL_WEEKDAY; + current.season = ORDINARY_TIME; + int sunday_counter = 34; + + snprintf(current.description, sizeof(current.description), + "%s of the %d%s Week in Ordinary Time", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + temp_days[temp_count++] = current; + + struct tm stop_date = add_days(pentecost_day.date, 1); + + while (compare_dates(current.date, stop_date) != 0) { + current.date = add_days(current.date, -1); + + if (current.date.tm_wday == 0) { + sunday_counter--; + } + + current.season = ORDINARY_TIME; + + if (current.date.tm_wday == 0) { + if (compare_dates(current.date, trinity_sunday) == 0) { + current.class = SOLEMNITY; + strcpy(current.description, "The Most Holy Trinity"); + } else if (compare_dates(current.date, corpus_christi) == 0) { + current.class = SOLEMNITY; + strcpy(current.description, "The Most Holy Body and Blood of Christ"); + } else if (sunday_counter == 33) { + current.class = SOLEMNITY; + strcpy(current.description, "Our Lord Jesus Christ, King of the Universe"); + } else { + current.class = SUNDAY; + snprintf(current.description, sizeof(current.description), + "%d%s Sunday of Ordinary Time", sunday_counter, + ordinal_suffix(sunday_counter)); + } + } else { + current.class = FERIAL_WEEKDAY; + snprintf(current.description, sizeof(current.description), + "%s of the %d%s week of Ordinary Time", + day_string(current.date.tm_wday), sunday_counter, + ordinal_suffix(sunday_counter)); + } + + temp_days[temp_count++] = current; + } + + // Reverse and add to main list + for (size_t i = temp_count; i > 0; i--) { + church_year_add(cy, temp_days[i - 1]); + } + + free(temp_days); +} + +ChurchYear proper_of_seasons(struct tm today) { + ChurchYear cy = church_year_new(); + + ChurchDay first_advent = first_sunday_advent(today.tm_year + 1900); + if (compare_dates(today, first_advent.date) < 0) { + first_advent = first_sunday_advent(today.tm_year + 1900 - 1); + } + + calculate_advent(&cy, &first_advent); + calculate_christmas(&cy, first_advent.date.tm_year + 1900); + + ChurchDay baptism_day = cy.days[cy.count - 1]; + ChurchDay easter = easter_for_year(baptism_day.date.tm_year + 1900); + ChurchDay ash_wed = ash_wednesday(&easter); + + calculate_otime_prelent(&cy, baptism_day); + calculate_lent(&cy, ash_wed); + + ChurchDay sat_before = cy.days[cy.count - 1]; + calculate_easter(&cy, sat_before); + + ChurchDay pentecost_day = cy.days[cy.count - 1]; + calculate_otime_posteaster(&cy, pentecost_day); + + return cy; +} diff --git a/src/builder.h b/src/builder.h new file mode 100644 index 0000000..af19e9b --- /dev/null +++ b/src/builder.h @@ -0,0 +1,10 @@ +#ifndef BUILDER_H +#define BUILDER_H + +#include "church_day.h" +#include + +//calculate proper of seasons for a given date +ChurchYear proper_of_seasons(struct tm today); + +#endif //BUILDER_H diff --git a/src/church_day.c b/src/church_day.c new file mode 100644 index 0000000..b700cce --- /dev/null +++ b/src/church_day.c @@ -0,0 +1,81 @@ +#include "church_day.h" +#include +#include +#include + +ChurchDay church_day_new(int year, int month, int day, DayClass class, Season season, const char *description) { + ChurchDay cd; + memset(&cd.date, 0, sizeof(struct tm)); + + cd.date.tm_year = year - 1900; + cd.date.tm_mon = month - 1; + cd.date.tm_mday = day; + + mktime(&cd.date); + + cd.class = class; + cd.season = season; + strncpy(cd.description, description, sizeof(cd.description) - 1); + cd.description[sizeof(cd.description) - 1] = '\0'; + + return cd; +} + +const char* church_day_month_name(const ChurchDay *day) { + static char buffer[32]; + strftime(buffer, sizeof(buffer), "%B", &day->date); + return buffer; +} + +const char* church_day_weekday_string(const ChurchDay *day) { + static char buffer[32]; + strftime(buffer, sizeof(buffer), "%A", &day->date); + return buffer; +} + +const char* day_class_to_string(DayClass class) { + switch (class) { + case SOLEMNITY: return "Solemnity"; + case SUNDAY: return "Sunday"; + case FEAST: return "Feast"; + case MEMORIAL: return "Memorial"; + case SEASONAL_WEEKDAY: return "Seasonal Weekday"; + case FERIAL_WEEKDAY: return "Ferial"; + default: return "Unknown"; + } +} + +const char* season_to_string(Season season) { + switch(season) { + case ADVENT: return "Advent"; + case CHRISTMAS: return "Christmas"; + case ORDINARY_TIME: return "Ordinary Time"; + case LENT: return "Lent"; + case TRIDUUM: return "Sacred Triduum"; + case EASTER: return "Easter"; + default: return "Unknown"; + } +} + +ChurchYear church_year_new(void) { + ChurchYear cy; + cy.capacity = 366; + cy.count = 0; + cy.days = malloc(cy.capacity * sizeof(ChurchDay)); + return cy; +} + +void church_year_add(ChurchYear *year, ChurchDay day) { + if (year->count >= year->capacity) { + year->capacity *= 2; + year->days = realloc(year->days, year->capacity * sizeof(ChurchDay)); + } + year->days[year->count++] = day; +} + +void church_year_free(ChurchYear *year) { + free(year->days); + year->days = NULL; + year->count = 0; + year->capacity = 0; +} diff --git a/src/church_day.h b/src/church_day.h new file mode 100644 index 0000000..e10f1c8 --- /dev/null +++ b/src/church_day.h @@ -0,0 +1,57 @@ +#ifndef CHURCH_DAY_H +#define CHURCH_DAY_H + +#include + +typedef enum { + SOLEMNITY, + SUNDAY, + FEAST, + MEMORIAL, + SEASONAL_WEEKDAY, + FERIAL_WEEKDAY +} DayClass; + +typedef enum { + ADVENT, + CHRISTMAS, + ORDINARY_TIME, + LENT, + TRIDUUM, + EASTER +} Season; + +typedef struct { + struct tm date; + DayClass class; + Season season; + char description[256]; +} ChurchDay; + +typedef struct { + ChurchDay *days; + size_t count; + size_t capacity; +} ChurchYear; + +//Create a new ChurchDay +ChurchDay church_day_new(int year, int month, int day, DayClass class, Season season, const char *description); + +//Get month name from ChurchDay +const char* church_day_month_name(const ChurchDay *day); + +//Get day of week string from ChurchDay +const char* church_day_weekday_string(const ChurchDay *day); + +//Get string representation of DayClass +const char* day_class_to_string(DayClass class); + +//Get string representation of Season +const char* season_to_string(Season season); + +//ChurchYear functions +ChurchYear church_year_new(void); +void church_year_add(ChurchYear *year, ChurchDay day); +void church_year_free(ChurchYear *year); + +#endif // CHURCH_DAY_H diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..1f86bc3 --- /dev/null +++ b/src/main.c @@ -0,0 +1,26 @@ +#include +#include +#include "church_day.h" +#include "builder.h" + +int main(void) { + time_t now = time(NULL); + struct tm *today = localtime(&now); + + ChurchYear seasons = proper_of_seasons(*today); + + for (size_t i = 0; i < seasons.count; i++) { + ChurchDay *day = &seasons.days[i]; + printf("%s, %s %d, %d - %s - %s in %s\n", + church_day_weekday_string(day), + church_day_month_name(day), + day->date.tm_mday, + day->date.tm_year + 1900, + day->description, + day_class_to_string(day->class), + season_to_string(day->season)); + } + + church_year_free(&seasons); + return 0; +}