mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
95 Weekday - move methods into appropriate? scopes or classes
This commit is contained in:
@@ -50,8 +50,10 @@ function tab(spaceCount) {
|
|||||||
|
|
||||||
const MONTHS_PER_YEAR = 12;
|
const MONTHS_PER_YEAR = 12;
|
||||||
const DAYS_PER_COMMON_YEAR = 365;
|
const DAYS_PER_COMMON_YEAR = 365;
|
||||||
const DAYS_PER_IDEAL_MONTH = 30;
|
const DAYS_PER_IDEALISED_MONTH = 30;
|
||||||
const MAXIMUM_DAYS_PER_MONTH = 31;
|
const MAXIMUM_DAYS_PER_MONTH = 31;
|
||||||
|
// In a common (non-leap) year the day of the week for the first of each month moves by the following amounts.
|
||||||
|
const COMMON_YEAR_MONTH_OFFSET = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date representation.
|
* Date representation.
|
||||||
@@ -105,6 +107,60 @@ class DateStruct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following performs a hash on the day parts which guarantees that
|
||||||
|
* 1. different days will return different numbers
|
||||||
|
* 2. the numbers returned are ordered.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getNormalisedDay() {
|
||||||
|
return (this.year * MONTHS_PER_YEAR + this.month) * MAXIMUM_DAYS_PER_MONTH + this.day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the day of the week.
|
||||||
|
* This calculation returns a number between 1 and 7 where Sunday=1, Monday=2, ..., Saturday=7.
|
||||||
|
* @returns {number} Value between 1 and 7 representing Sunday to Saturday.
|
||||||
|
*/
|
||||||
|
getDayOfWeek() {
|
||||||
|
// Calculate an offset based on the century part of the year.
|
||||||
|
const centuriesSince1500 = Math.floor((this.year - 1500) / 100);
|
||||||
|
let centuryOffset = centuriesSince1500 * 5 + (centuriesSince1500 + 3) / 4;
|
||||||
|
centuryOffset = Math.floor(centuryOffset % 7);
|
||||||
|
|
||||||
|
// Calculate an offset based on the shortened two digit year.
|
||||||
|
// January 1st moves forward by approximately 1.25 days per year
|
||||||
|
const yearInCentury = this.year % 100;
|
||||||
|
const yearInCenturyOffsets = yearInCentury / 4 + yearInCentury;
|
||||||
|
|
||||||
|
// combine offsets with day and month
|
||||||
|
let dayOfWeek = centuryOffset + yearInCenturyOffsets + this.day + COMMON_YEAR_MONTH_OFFSET[this.month - 1];
|
||||||
|
|
||||||
|
dayOfWeek = Math.floor(dayOfWeek % 7) + 1;
|
||||||
|
if (this.month <= 2 && this.isLeapYear()) {
|
||||||
|
dayOfWeek--;
|
||||||
|
}
|
||||||
|
if (dayOfWeek === 0) {
|
||||||
|
dayOfWeek = 7;
|
||||||
|
}
|
||||||
|
return dayOfWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given year is a leap year.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isLeapYear() {
|
||||||
|
if ((this.year % 4) !== 0) {
|
||||||
|
return false;
|
||||||
|
} else if ((this.year % 100) !== 0) {
|
||||||
|
return true;
|
||||||
|
} else if ((this.year % 400) !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a US formatted date, i.e. Month/Day/Year.
|
* Returns a US formatted date, i.e. Month/Day/Year.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
@@ -169,7 +225,7 @@ class Duration {
|
|||||||
*/
|
*/
|
||||||
#fixRanges() {
|
#fixRanges() {
|
||||||
if (this.#days < 0) {
|
if (this.#days < 0) {
|
||||||
this.#days += DAYS_PER_IDEAL_MONTH;
|
this.#days += DAYS_PER_IDEALISED_MONTH;
|
||||||
this.#months--;
|
this.#months--;
|
||||||
}
|
}
|
||||||
if (this.#months < 0) {
|
if (this.#months < 0) {
|
||||||
@@ -178,10 +234,6 @@ class Duration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
|
||||||
return this.#years + "/" + this.#months + "/" + this.#days;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine approximate Duration between two dates.
|
* Determine approximate Duration between two dates.
|
||||||
* This is a naive calculation which assumes all months are 30 days.
|
* This is a naive calculation which assumes all months are 30 days.
|
||||||
@@ -195,146 +247,90 @@ class Duration {
|
|||||||
let days = date1.day - date2.day;
|
let days = date1.day - date2.day;
|
||||||
return new Duration(years, months, days);
|
return new Duration(years, months, days);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// In a common (non-leap) year the day of the week for the first of each month moves by the following amounts.
|
/**
|
||||||
const COMMON_YEAR_MONTH_OFFSET = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5];
|
* Calculate years, months and days as factor of days.
|
||||||
|
* This is a naive calculation which assumes all months are 30 days.
|
||||||
/**
|
* @param dayCount Total day to convert to a duration
|
||||||
* Reads a date, and extracts the date information.
|
* @param factor Factor to apply when calculating the duration
|
||||||
* This expects date parts to be comma separated, using US date ordering,
|
* @returns {Duration}
|
||||||
* i.e. Month,Day,Year.
|
*/
|
||||||
* @returns {Promise<DateStruct>}
|
static fromDays(dayCount, factor) {
|
||||||
*/
|
let totalDays = Math.floor(factor * dayCount);
|
||||||
async function readDateElements() {
|
const years = Math.floor(totalDays / DAYS_PER_COMMON_YEAR);
|
||||||
let dateString = await input();
|
totalDays -= years * DAYS_PER_COMMON_YEAR;
|
||||||
const month = parseInt(dateString);
|
const months = Math.floor(totalDays / DAYS_PER_IDEALISED_MONTH);
|
||||||
const day = parseInt(dateString.substr(dateString.indexOf(",") + 1));
|
const days = totalDays - (months * DAYS_PER_IDEALISED_MONTH);
|
||||||
const year = parseInt(dateString.substr(dateString.lastIndexOf(",") + 1));
|
return new Duration(years, months, days);
|
||||||
return new DateStruct(year, month, day);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate years, months and days as factor of days.
|
|
||||||
* This is a naive calculation which assumes all months are 30 days.
|
|
||||||
* @param factor
|
|
||||||
* @param dayCount
|
|
||||||
* @returns {Duration}
|
|
||||||
*/
|
|
||||||
function time_spent(factor, dayCount) {
|
|
||||||
let totalDays = Math.floor(factor * dayCount);
|
|
||||||
const years = Math.floor(totalDays / DAYS_PER_COMMON_YEAR);
|
|
||||||
totalDays -= years * DAYS_PER_COMMON_YEAR;
|
|
||||||
const months = Math.floor(totalDays / DAYS_PER_IDEAL_MONTH);
|
|
||||||
const days = totalDays - (months * DAYS_PER_IDEAL_MONTH);
|
|
||||||
return new Duration(years, months, days);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the supplied duration.
|
|
||||||
* @param {Duration} duration
|
|
||||||
*/
|
|
||||||
function printTimeSpent(duration) {
|
|
||||||
print(duration.years + "\t" + duration.months + "\t" + duration.days + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the given year is a leap year.
|
|
||||||
* @param year
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function isLeapYear(year) {
|
|
||||||
if ((year % 4) !== 0) {
|
|
||||||
return false;
|
|
||||||
} else if ((year % 100) !== 0) {
|
|
||||||
return true;
|
|
||||||
} else if ((year % 400) !== 0) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
toString() {
|
||||||
* Determine the day of the week.
|
return this.#years + "/" + this.#months + "/" + this.#days;
|
||||||
* This calculation returns a number between 1 and 7 where Sunday=1, Monday=2, ..., Saturday=7.
|
|
||||||
* @param {DateStruct} date
|
|
||||||
* @returns {number} Value between 1 and 7 representing Sunday to Saturday.
|
|
||||||
*/
|
|
||||||
function getDayOfWeek(date) {
|
|
||||||
// Calculate an offset based on the century part of the year.
|
|
||||||
const centuriesSince1500 = Math.floor((date.year - 1500) / 100);
|
|
||||||
let centuryOffset = centuriesSince1500 * 5 + (centuriesSince1500 + 3) / 4;
|
|
||||||
centuryOffset = Math.floor(centuryOffset % 7);
|
|
||||||
|
|
||||||
// Calculate an offset based on the shortened two digit year.
|
|
||||||
// January 1st moves forward by approximately 1.25 days per year
|
|
||||||
const yearInCentury = date.year % 100;
|
|
||||||
const yearInCenturyOffsets = yearInCentury / 4 + yearInCentury;
|
|
||||||
|
|
||||||
// combine offsets with day and month
|
|
||||||
let dayOfWeek = centuryOffset + yearInCenturyOffsets + date.day + COMMON_YEAR_MONTH_OFFSET[date.month - 1];
|
|
||||||
|
|
||||||
dayOfWeek = Math.floor(dayOfWeek % 7) + 1;
|
|
||||||
if (date.month <= 2 && isLeapYear(date.year)) {
|
|
||||||
dayOfWeek--;
|
|
||||||
}
|
}
|
||||||
if (dayOfWeek === 0) {
|
|
||||||
dayOfWeek = 7;
|
|
||||||
}
|
|
||||||
return dayOfWeek;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain text for the day of the week.
|
|
||||||
* @param {DateStruct} date
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function getDayOfWeekText(date) {
|
|
||||||
const dayOfWeek = getDayOfWeek(date);
|
|
||||||
let dayOfWeekText = "";
|
|
||||||
switch (dayOfWeek) {
|
|
||||||
case 1:
|
|
||||||
dayOfWeekText = "SUNDAY.";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dayOfWeekText = "MONDAY.";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
dayOfWeekText = "TUESDAY.";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dayOfWeekText = "WEDNESDAY.";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
dayOfWeekText = "THURSDAY.";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
if (date.day === 13) {
|
|
||||||
dayOfWeekText = "FRIDAY THE THIRTEENTH---BEWARE!";
|
|
||||||
} else {
|
|
||||||
dayOfWeekText = "FRIDAY.";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
dayOfWeekText = "SATURDAY.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return dayOfWeekText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The following performs a hash on the day parts which guarantees that
|
|
||||||
* 1. different days will return different numbers
|
|
||||||
* 2. the numbers returned are ordered.
|
|
||||||
* @param {DateStruct} date
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
function getNormalisedDay(date) {
|
|
||||||
return (date.year * MONTHS_PER_YEAR + date.month) * MAXIMUM_DAYS_PER_MONTH + date.day;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main control section
|
// Main control section
|
||||||
async function main() {
|
async function main() {
|
||||||
|
/**
|
||||||
|
* Reads a date, and extracts the date information.
|
||||||
|
* This expects date parts to be comma separated, using US date ordering,
|
||||||
|
* i.e. Month,Day,Year.
|
||||||
|
* @returns {Promise<DateStruct>}
|
||||||
|
*/
|
||||||
|
async function inputDate() {
|
||||||
|
let dateString = await input();
|
||||||
|
const month = parseInt(dateString);
|
||||||
|
const day = parseInt(dateString.substr(dateString.indexOf(",") + 1));
|
||||||
|
const year = parseInt(dateString.substr(dateString.lastIndexOf(",") + 1));
|
||||||
|
return new DateStruct(year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the supplied duration.
|
||||||
|
* @param {Duration} duration
|
||||||
|
*/
|
||||||
|
function printTimeSpent(duration) {
|
||||||
|
print(duration.years + "\t" + duration.months + "\t" + duration.days + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain text for the day of the week.
|
||||||
|
* @param {DateStruct} date
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function getDayOfWeekText(date) {
|
||||||
|
const dayOfWeek = date.getDayOfWeek();
|
||||||
|
let dayOfWeekText = "";
|
||||||
|
switch (dayOfWeek) {
|
||||||
|
case 1:
|
||||||
|
dayOfWeekText = "SUNDAY.";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dayOfWeekText = "MONDAY.";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
dayOfWeekText = "TUESDAY.";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
dayOfWeekText = "WEDNESDAY.";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
dayOfWeekText = "THURSDAY.";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if (date.day === 13) {
|
||||||
|
dayOfWeekText = "FRIDAY THE THIRTEENTH---BEWARE!";
|
||||||
|
} else {
|
||||||
|
dayOfWeekText = "FRIDAY.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
dayOfWeekText = "SATURDAY.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return dayOfWeekText;
|
||||||
|
}
|
||||||
|
|
||||||
print(tab(32) + "WEEKDAY\n");
|
print(tab(32) + "WEEKDAY\n");
|
||||||
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
|
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
|
||||||
print("\n");
|
print("\n");
|
||||||
@@ -344,18 +340,18 @@ async function main() {
|
|||||||
print("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU.\n");
|
print("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU.\n");
|
||||||
print("\n");
|
print("\n");
|
||||||
print("ENTER TODAY'S DATE IN THE FORM: 3,24,1979 ");
|
print("ENTER TODAY'S DATE IN THE FORM: 3,24,1979 ");
|
||||||
const today = await readDateElements();
|
const today = await inputDate();
|
||||||
// This program determines the day of the week
|
// This program determines the day of the week
|
||||||
// for a date after 1582
|
// for a date after 1582
|
||||||
print("ENTER DAY OF BIRTH (OR OTHER DAY OF INTEREST)");
|
print("ENTER DAY OF BIRTH (OR OTHER DAY OF INTEREST)");
|
||||||
const dateOfBirth = await readDateElements();
|
const dateOfBirth = await inputDate();
|
||||||
print("\n");
|
print("\n");
|
||||||
// Test for date before current calendar.
|
// Test for date before current calendar.
|
||||||
if (!dateOfBirth.isGregorianDate()) {
|
if (!dateOfBirth.isGregorianDate()) {
|
||||||
print("NOT PREPARED TO GIVE DAY OF WEEK PRIOR TO X.XV.MDLXXXII.\n");
|
print("NOT PREPARED TO GIVE DAY OF WEEK PRIOR TO X.XV.MDLXXXII.\n");
|
||||||
} else {
|
} else {
|
||||||
const normalisedToday = getNormalisedDay(today);
|
const normalisedToday = today.getNormalisedDay();
|
||||||
const normalisedDob = getNormalisedDay(dateOfBirth);
|
const normalisedDob = dateOfBirth.getNormalisedDay();
|
||||||
|
|
||||||
let dayOfWeekText = getDayOfWeekText(dateOfBirth);
|
let dayOfWeekText = getDayOfWeekText(dateOfBirth);
|
||||||
if (normalisedToday < normalisedDob) {
|
if (normalisedToday < normalisedDob) {
|
||||||
@@ -377,29 +373,29 @@ async function main() {
|
|||||||
print(" \t-----\t------\t----\n");
|
print(" \t-----\t------\t----\n");
|
||||||
print("YOUR AGE (IF BIRTHDATE) \t");
|
print("YOUR AGE (IF BIRTHDATE) \t");
|
||||||
printTimeSpent(differenceBetweenDates);
|
printTimeSpent(differenceBetweenDates);
|
||||||
const approximateDaysBetween = (differenceBetweenDates.years * DAYS_PER_COMMON_YEAR) + (differenceBetweenDates.months * DAYS_PER_IDEAL_MONTH) + differenceBetweenDates.days + Math.floor(differenceBetweenDates.months / 2);
|
const approximateDaysBetween = (differenceBetweenDates.years * DAYS_PER_COMMON_YEAR) + (differenceBetweenDates.months * DAYS_PER_IDEALISED_MONTH) + differenceBetweenDates.days + Math.floor(differenceBetweenDates.months / 2);
|
||||||
// Create an object containing time unaccounted for
|
// Create an object containing time unaccounted for
|
||||||
const unaccountedTime = differenceBetweenDates.clone();
|
const unaccountedTime = differenceBetweenDates.clone();
|
||||||
|
|
||||||
// Calculate time spent in the following functions.
|
// Calculate time spent in the following functions.
|
||||||
print("YOU HAVE SLEPT \t\t\t");
|
print("YOU HAVE SLEPT \t\t\t");
|
||||||
const sleepTimeSpent = time_spent(0.35, approximateDaysBetween);
|
const sleepTimeSpent = Duration.fromDays(approximateDaysBetween, 0.35);
|
||||||
printTimeSpent(sleepTimeSpent);
|
printTimeSpent(sleepTimeSpent);
|
||||||
|
|
||||||
unaccountedTime.remove(sleepTimeSpent);
|
unaccountedTime.remove(sleepTimeSpent);
|
||||||
print("YOU HAVE EATEN \t\t\t");
|
print("YOU HAVE EATEN \t\t\t");
|
||||||
const eatenTimeSpent = time_spent(0.17, approximateDaysBetween);
|
const eatenTimeSpent = Duration.fromDays(approximateDaysBetween, 0.17);
|
||||||
printTimeSpent(eatenTimeSpent);
|
printTimeSpent(eatenTimeSpent);
|
||||||
|
|
||||||
unaccountedTime.remove(eatenTimeSpent);
|
unaccountedTime.remove(eatenTimeSpent);
|
||||||
if (unaccountedTime.years <= 3) {
|
if (unaccountedTime.years <= 3) {
|
||||||
print("YOU HAVE PLAYED \t\t");
|
print("YOU HAVE PLAYED \t\t");
|
||||||
} else if (unaccountedTime.years <= 9) {
|
} else if (unaccountedTime.years <= 9) {
|
||||||
print("YOU HAVE PLAYED/STUDIED \t\t");
|
print("YOU HAVE PLAYED/STUDIED \t");
|
||||||
} else {
|
} else {
|
||||||
print("YOU HAVE WORKED/PLAYED \t\t");
|
print("YOU HAVE WORKED/PLAYED \t\t");
|
||||||
}
|
}
|
||||||
const workPlayTimeSpent = time_spent(0.23, approximateDaysBetween);
|
const workPlayTimeSpent = Duration.fromDays(approximateDaysBetween, 0.23);
|
||||||
printTimeSpent(workPlayTimeSpent);
|
printTimeSpent(workPlayTimeSpent);
|
||||||
|
|
||||||
unaccountedTime.remove(workPlayTimeSpent);
|
unaccountedTime.remove(workPlayTimeSpent);
|
||||||
|
|||||||
Reference in New Issue
Block a user