From f7851ebc2a551c78851cba076af44b5e336d9a65 Mon Sep 17 00:00:00 2001 From: hashcatHitman <155700084+hashcatHitman@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:23:51 -0500 Subject: [PATCH] Project Setup, First Working Version Files related to CLion project setup, and the first working version of the program. --- .idea/PUNCHCARD.iml | 2 + .idea/misc.xml | 7 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 + CMakeLists.txt | 6 + PUNCHCARD.c | 275 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 304 insertions(+) create mode 100644 .idea/PUNCHCARD.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 CMakeLists.txt create mode 100644 PUNCHCARD.c diff --git a/.idea/PUNCHCARD.iml b/.idea/PUNCHCARD.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/PUNCHCARD.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..df5c705 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fed47de --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.29) +PROJECT(PUNCHCARD C) + +SET(CMAKE_C_STANDARD 23) + +ADD_EXECUTABLE(PUNCHCARD PUNCHCARD.c) diff --git a/PUNCHCARD.c b/PUNCHCARD.c new file mode 100644 index 0000000..b3713ae --- /dev/null +++ b/PUNCHCARD.c @@ -0,0 +1,275 @@ +/** + * @author Sam K + * @date October 8th, 2024 + * @name PUNCHCARD + * + * @details A simple terminal program meant to simplify calculating work-hours + * calculations for employees. At the time of writing, employees are required to + * round their worked hours to the nearest quarter-hour (X.00, X.25, X.50, X.75, + * X+1.00). This program takes a start time and end time separated by a hyphen + * and determines the hours worked, assuming the hours worked are less than 24 + * and that the start and end times are always in the order start - end, such + * that working from 8:00pm-7:59pm is a valid input, suggesting you worked 23 + * hours and 59 minutes. The program will continue to do this repeatedly until + * stopped. You can stop the program with Ctrl + C, closing the window, or + * entering the same start and end time. + */ + +// Libraries in use: +#include + +// Functions +/** + * Skips past any unwanted characters between the start time and end time. + */ +void skipBufferJunk() { + int temporary; + while ((temporary = getchar()) != '-' && temporary != EOF) {} +} + +/** + * Flushes the input buffer. + */ +void cleanBuffer() { + int temporary; + while ((temporary = getchar()) != '\n' && temporary != EOF ) {} +} + +/** + * Attempts to read the next available time from stdin, in the format HH:MMcc, + * where HH is the hour, MM is the minute, and cc is the meridiem indicator + * ("am" or "pm"). + * + * @param hour A pointer to the int storing the hour for this time. + * @param minute A pointer to the int storing the minute for this time. + * @param meridiem A pointer to the char storing the meridiem indicator for + * this time. + * + * @return 0 if a valid time was read, -1 if something wasn't right with the + * read time. + */ +int readTime(int* hour, int* minute, char* meridiem) { + // Scan the time in. + scanf_s(" %d : %d %c", hour, minute, meridiem); + + // It's a lot easier if we just convert uppercase to lowercase. + if (*meridiem == 'A') { + *meridiem = 'a'; + } else if (*meridiem == 'P') { + *meridiem = 'p'; + } + + // If we got what looks like a valid time, return 0. + if (*hour > 0 && *hour < 13 && *minute > -1 && *minute < 60 && + (*meridiem == 'a' || *meridiem == 'p')) { + return 0; + // Else... + } else { + // Print a message explaining what was wrong, return -1. + if (*hour <= 0) { + printf_s("[ERROR]\tHOUR TOO SMALL: \"%d\", should be " + "greater than 0.\n", *hour); + } + if (*hour >= 13) { + printf_s("[ERROR]\tHOUR TOO BIG: \"%d\", should be less " + "than 13.\n", *hour); + } + if (*minute <= -1) { + printf_s("[ERROR]\tMINUTE TOO SMALL: \"%d\", should be " + "greater than -1.\n", *minute); + } + if (*minute >= 60) { + printf_s("[ERROR]\tMINUTE TOO BIG: \"%d\", should be less " + "than 60.\n", *minute); + } + if ((*meridiem != (int) 'a') && (*meridiem != (int) 'p')) { + printf_s("[ERROR]\tUNRECOGNIZED MERIDIEM: \"%cm\", should " + "be \"am\" or \"pm\".\n", *meridiem); + } + return -1; + } +} + +/** + * Converts 12-hour time to 24-hour time, because it is easier to do math with. + * + * @param hour A pointer to the int storing the hour for the time to convert. + * @param meridiem A pointer to the char storing the meridiem indicator for the + * time to convert. + */ +void toMilitaryTime(int* hour, const char* meridiem) { + // If it's the 12th hour... + if (*hour == 12) { + // ...and the am, add 12 so 12am = 24:00/00:00. + if (*meridiem == 'a') { + *hour += 12; + } + // Else... + } else { + // ...if it's the pm, add 12. + if (*meridiem == 'p') { + *hour += 12; + } + } +} + +/** + * Rounds the time difference to the nearest quarter-hour. + * + * @param hourDifference A pointer to the integer storing the hour portion of + * the time spent working. + * @param minuteDifference A pointer to the integer storing the minutes portion + * of the time spent working. + */ +void roundTime(int* hourDifference, int* minuteDifference) { + // Round the minutes worked to the nearest multiple of 15. + *minuteDifference = ((*minuteDifference + 7) / 15) * 15; + + // If rounded to 60 minutes, reset to 0 and increment hours worked. + if (*minuteDifference == 60) { + *minuteDifference = 0; + (*hourDifference)++; + } +} + +/** + * Gives the user a brief introduction, then prompts the user to enter their + * start and end times. Calculates the hours worked, and presents the actual + * work time as well as the rounded hours format. Repeats this process starting + * from prompting the user until the program is stopped in some way or the user + * enters the exact same start and end time. + */ +int main(void) { + // Introduction + printf_s("\nWelcome to PUNCHCARD! This program is meant to help you " + "record your work hours\nas an employee. To get started, just " + "enter your start time and end time, in the\nformat " + "HH:MMcc-HH:MMcc. For example, if you worked from noon to 3pm " + "today, you'd\nenter 12:00pm-3:00pm. You can quit the program by " + "closing this window, pressing\nCtrl + C, or entering a start " + "time and end time that are identical (such as\n1:00pm-1:00pm)" + ".\n\n"); + + // Until given a reason to stop... + while (1) { + // Declare our variables... + /** + * The hour work was started at (12-hour time). + */ + int startHour; + + /** + * The minute work was started at. + */ + int startMinute; + + /** + * The first character of the meridiem indicator for the time work was + * started at ('a' or 'p'). + */ + char startMeridiem; + + /** + * The hour work ended at (12-hour time). + */ + int endHour; + + /** + * The minute work ended at. + */ + int endMinute; + + /** + * The first character of the meridiem indicator for the time work + * ended at ('a' or 'p'). + */ + char endMeridiem; + + /** + * The hour value of the difference between the end time and start time. + */ + int hourDifference; + + /** + * The minute value of the difference between the end time and start + * time. + */ + int minuteDifference; + + /** + * The time spent working in hours, rounded to the nearest quarter-hour. + */ + float roundedTime; + + // Prompt the user. + printf_s("Enter your times:\n"); + + // Read the start time. If something went wrong... + if (readTime(&startHour, &startMinute, &startMeridiem) == -1) { + // Clean the buffer and try again. + printf_s("Something was wrong with your given start time!\n"); + cleanBuffer(); + continue; + } + + // Skip anything particularly annoying between the two times. + skipBufferJunk(); + + // Read the end time. If something went wrong... + if (readTime(&endHour, &endMinute, &endMeridiem) == -1) { + // Clean the buffer and try again. + printf_s("Something was wrong with your given end time!\n"); + cleanBuffer(); + continue; + } + + // Print the times read back, for confirmation/debugging reasons. + printf_s("\n"); + printf_s("START:\t%02d:%02d%cm\n", startHour, startMinute, + startMeridiem); + printf_s("END:\t%02d:%02d%cm\n", endHour, endMinute, endMeridiem); + + // If the start time and end time are identical... + if (startHour == endHour && startMinute == endMinute && startMeridiem + == endMeridiem) { + // Stop the program, we're done here. + break; + } + + // Convert both times to 24-hour time. + toMilitaryTime(&startHour, &startMeridiem); + toMilitaryTime(&endHour, &endMeridiem); + + // Calculate the difference + hourDifference = endHour - startHour; + minuteDifference = endMinute - startMinute; + + // If the minutes are less than 0... + if (minuteDifference < 0) { + // Tick down an hour and set the minutes to the correct value. + hourDifference--; + minuteDifference += 60; + } + + // If the hour is less than 0... + if (hourDifference < 0) { + // Add 24 to find the actual hour. + hourDifference += 24; + } + + // Print the time worked. + printf_s("ACTUAL TIME:\t%02d hours and %02d minutes.\n", hourDifference, + minuteDifference); + + // Round to the nearest quarter-hour and print. + roundTime(&hourDifference, &minuteDifference); + roundedTime = ((float) minuteDifference / 60) + (float) hourDifference; + printf_s("ROUNDED TIME:\t%0.2f hours.\n\n", roundedTime); + + // Clean the buffer before the next iteration. + cleanBuffer(); + } + + // Finish the program. + return 0; +}