// # CS1 u6_weekday.c
// Jonas Altrock <ew20b126@technikum-wien.at>
//
// [To overview](../).
//
// [The whole source file `u6_weekday.c`.](./u6_weekday.c)
/* Compile with `clang -std=c99 -Wall -o u6_weekday u6_weekday.c` */
/* Test with `../checkproject u6_weekday` */

// Include C-libraries for input/output.
#include <stdio.h>
#include <stdlib.h>

// Exercise 6: Procedures: Day of Week
// ===================================
//
// Find the day of week of a given date past the year 1583.
//
// ## Details
// Read a date in the format `yyyy-mm-dd` (same as Exercise 4) and then print
// the day of week. Use capitalization, i.e. print the first letter in upper
// case and the remaining letters in lower case!
//
// You may assume that the date is always valid and `yyyy` is larger or equal
// 1584.
//
// For this exercise, it is required to use multiple procedures - please, find
// and implement reasonable functions with their own responsibilities!
//
// ### Hints
// There are many ways to solve this exercise (see for instance Wikipedia -
// Doomsday Rule. The following is a suggestion how to solve it. You are free
// to take some of these hints or proposals or to write your own version but it
// is not allowed to call an inbuilt function that already solves this exercise.
//
// #### Split the exercise into multiple smaller exercises
// Identify useful procedures. The following sketch could help you:
//
// *Count the number of days passed since the first of january 1584 (which was
//   a Sunday).*
//
// * For all years before the entered year find out the number of days passed
//   since (including) the year 1584 (procedure `daysBefore(int year)`)
//   - Find out how many days a given year has.
//     * Check whether a given year is a leap year (procedure
//       `isLeapYear(int year)`)
// * Find out how many days have passed since the 1st of January of the entered
//   year (= sum of days of passed in previous months)
//   - Find out how many days a given month has (procedure `daysInMonth`)
//     * Depends on the year (leap years)!
//
// From these values you can calculate the number of days passed since the first
// of january 1584.
//
// From the number of days passed since the first of january 1584 you can find
// the day of the week of the entered day using modulo 7. If the result is 0,
// then the day is a Sunday (because the 1st of january 1584 was a Sunday),
// if it is 1 a Monday, etc. ...
//
// Make sure that during implementing procedures you check whether they return
// correct values.
//
// ### Remark
// The year 1584 is picked in this exercise because it is the first year after
// the introduction of the Gregorian calendar such that the 1st of January is a
// Sunday.
//
// ### Example 1
// Input:
// ```
// 2016-8-12
// ```
// Output:
// ```
// Friday
// ```
// ### Example 2
// Input:
// ```
// 1585-1-1
// ```
// Output:
// ```
// Tuesday
// ```

// ## Forward declarations
// [days_since_1584](#days_since_1584),
// [days_in_month](#days_in_month),
// [is_leap_year](#is_leap_year),
// [day_of_week](#day_of_week).
int days_since_1584(int y, int m, int d);
int days_in_month(int y, int m);
int is_leap_year(int y);
const char *day_of_week(int d);

// ## main()
// Implement the solution by
int main() {
    int yyyy, mm, dd;
// reading in the date in the format YYYY-MM-DD,
    scanf("%04d-%02d-%02d", &yyyy, &mm, &dd);
// calculating the number of days since 1st of January, 1584,
    int days = days_since_1584(yyyy, mm, dd);
// and then printing the day the week for the given date from that number.
    printf("%s\n", day_of_week(days));
    return 0;
}

// ## days_since_1584()
// Count days since 1st of January 1584 (which was Sunday).
int days_since_1584(int y, int m, int d) {
    int days = 0;

    // Loop through years before the given year, and sum their days.
    for (int i = 1584; i < y; i++) {
        if (is_leap_year(i)) {
            days += 366;
        } else {
            days += 365;
        }
    }

    // Loop through months in the given year, and sum their days.
    for (int j = 1; j < m; j++) {
        days += days_in_month(y, j);
    }

    // Finally add the days in the given month (`-1` because jan 1st
    // is the reference date).
    days += d - 1;

    // Return the total number of days.
    return days;
}

// ## is_leap_year()
// Check if a given year is a leap year. Returns `1` or `0`.
int is_leap_year(int y) {
    // Leap years must be divisible by 4.
    if (y % 4 != 0) return 0;
    // Not a leap year if divisible by 100, except if divisible by 400.
    if (y % 100 == 0 && y % 400 != 0) return 0;
    // Otherwise, a leap year.
    return 1;
}

// ## days_in_month()
// Get the number of days in a given month of a given year.
// Takes into account that February has 29 days in a leap year.
int days_in_month(int y, int m) {
    if (m == 1) return 31;
    if (m == 2) return 28 + is_leap_year(y);
    if (m == 3) return 31;
    if (m == 4) return 30;
    if (m == 5) return 31;
    if (m == 6) return 30;
    if (m == 7) return 31;
    if (m == 8) return 31;
    if (m == 9) return 30;
    if (m == 10) return 31;
    if (m == 11) return 30;
    if (m == 12) return 31;
    return 0; // *shrug*
}

// ## day_of_week()
// Get the name of the day in the week. Argument is the number of days
// since January 1st, 1584, which was a Sunday.
const char *day_of_week(int d) {
    // Modulo 7, as the hint suggested.
    d = d % 7;
    // Then give the string constant depending on the result (0 to 6).
    if (d == 0) return "Sunday";
    if (d == 1) return "Monday";
    if (d == 2) return "Tuesday";
    if (d == 3) return "Wednesday";
    if (d == 4) return "Thursday";
    if (d == 5) return "Friday";
    return "Saturday";
}