/* NOC Schedule Calculator - Copyright 2003 Travis Morgan Started Nov 25th, 2003 Version 1.0 - Dec 09th, 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software */ #include #include #include #include #include #define NUMVALUES (5) #define MAXNAMELEN (10) #define MAXBUF (1000) char targets[NUMVALUES][MAXNAMELEN]={"name=","work=","shift=","month=","year="}; char highlights[2][3][30]={"" , "" , "" , "" , "" , ""}; int getvalues(const char buff[MAXBUF], const char *endptr, char targets[NUMVALUES][MAXNAMELEN], char values[NUMVALUES][MAXBUF]); int leapyear(int year); void pad(int tab); int calcdistance(int cur_day, int cur_month, int cur_year, int start_day, int start_month, int start_year, int numdays[12]); int highlight(int cur_day, int cur_month, int cur_year, int start_day, int start_month, int start_year, int nights, int working, int weekday, int numdays[12]); int calcfirstweekday(int month, int year, int numdays[12]); int printmonth(int month, int year, int start_day, int start_month, int start_year, int nights, int working, int weekday, int numdays[12], int tab); int makesched(char values[NUMVALUES][MAXBUF]); int main() { int i = 0; char values[NUMVALUES][MAXBUF]; char *endptr; double dlen; char buff[MAXBUF]; const char *clen = getenv("CONTENT_LENGTH"); dlen = strtol(clen, &endptr, 10); if (dlen >= MAXBUF) { printf("Content-type: text/html\n\nWhat are you doing to my poor script?\n"); return 0; } fread(buff, dlen, 1, stdin); getvalues(buff,endptr,targets,values); printf("Content-type: text/html\n\n\n"); printf(" \n"); printf(" NOC Schedule for %s\n",values[0]); printf(" \n"); printf("
\n"); printf(" NOC Schedule for %s
\n",values[0]); makesched(values); printf(" Version 1.0 - Dec 09, 2003 - Travis Morgan\n"); printf("
\n"); printf("\n"); return 0; } void pad(int tab) { int i; for (i=1;i<=tab;i++) printf(" "); return; } int calcfirstweekday(int month, int year, int numdays[12]) { // TODO: make this use calcdistance and weekday so // it doesn't depend on 1989 int start = 1989; int total_days = 0; while (start < year) { if (leapyear(start)==1) total_days += 366; else total_days += 365; start++; } start = 0; while (start < month) { if (start == 1) { if (leapyear(year) == 1) total_days += 29; else total_days += 28; } else total_days += numdays[start]; start++; } return (total_days % 7); } int leapyear(int year) { if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))) return 1; return 0; } int calcdistance(int cur_day, int cur_month, int cur_year, int start_day, int start_month, int start_year, int numdays[12]) { // only counts forward so will recurse going other direction if necessary int distance = 0; int temp; // printf("%d %d %d %d %d %d\n",cur_day, cur_month, cur_year, start_day, start_month, start_year); // return 0; if (cur_year != start_year) // working with different years { if (cur_year > start_year) // call it again going the other direction distance += calcdistance(start_day, start_month, start_year, cur_day, cur_month, cur_year, numdays); else { temp = cur_year + 1; while (temp < start_year) { if (leapyear(temp) == 0) distance += 365; else distance += 366; temp++; } // add distance from cur_day to the next year distance += calcdistance(cur_day, cur_month, cur_year, 31, 11, cur_year, numdays) + 1; // add distance from start of the year to start_day distance += calcdistance(1, 0, start_year, start_day, start_month, start_year, numdays); } } else if (cur_month != start_month) // working within the same year { if (cur_month > start_month) // call it again going the other direction distance += calcdistance(start_day, start_month, start_year, cur_day, cur_month, cur_year, numdays); else { temp = cur_month +1; while (temp < start_month) { if ((temp == 1)&&(leapyear(start_year) == 1)) distance += 29; else distance += numdays[temp]; temp++; } if ((cur_month == 1) && (leapyear(cur_year) == 1)) temp = 29; else temp = numdays[cur_month]; // add distance from current day to the start of next month distance += calcdistance(cur_day, cur_month, cur_year, temp, cur_month, cur_year, numdays) + 1; // add distance from 1st of start_month the start_day distance += calcdistance(1, start_month, start_year, start_day, start_month, start_year, numdays); } } else distance += abs(start_day - cur_day); return distance; } int highlight(int cur_day, int cur_month, int cur_year, int start_day, int start_month, int start_year, int nights, int working, int weekday, int numdays[12]) { // returns: // 0 - not working // 1 - working days // 2 - working nights // TODO: take your head out of your ass int distance, dir, pos, cur_pos; // F S S M T W T F S S M T W T int sched[14]={1,1,1,0,0,1,1,0,0,0, 1, 1, 0, 0}; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 // 0 1 2 3 4 5 6 // S M T W T F S distance = calcdistance(cur_day, cur_month, cur_year, start_day, start_month, start_year, numdays); if ((cur_year < start_year) || ((cur_year == start_year)&&(cur_month < start_month)) || ((cur_year == start_year)&&(cur_month == start_month)&&(cur_day < start_day))) dir = -1; else dir = 1; // find todays position in the schedule pos = weekday - 5; // friday is 0 in the schedule if (pos < 0) pos = pos + 7; // land inside range of 0 to 13 if (sched[pos] != working) // must be in second half of schedule pos = pos + 7; cur_pos = pos + (dir * distance); // go forwards or backwards in the schedule the right number of days while ((cur_pos < 0) || (cur_pos > 13)) // land inside the scope { cur_pos = cur_pos + -14 * dir; // get one period closer nights = (nights + 1) % 2; // nights and days flip } working = sched[cur_pos]; // grab the position out of the schedule if (working == 0) // not working return 0; if (nights == 0) // working days return 1; return 2; // working nights } int printmonth(int month, int year, int start_day, int start_month, int start_year, int nights, int working, int weekday, int numdays[12], int tab) { char smonth[12][10]={"January","February","March","April","May","June","July","August","September","October","November","December"}; int day, col, hl; // start table and print headings pad(tab); printf("\n"); pad(tab+1); printf("\n",smonth[month],year); pad(tab+1); printf("\n"); day = calcfirstweekday(month,year,numdays); // pad up to the first of the month col = 0; while (day > 0) { if (col == 0) { pad(tab+1); printf(""); } printf(""); day--; col++; } // print days of month for (day = 1; day <= numdays[month]; day++) { if (col == 0) { pad(tab+1); printf(""); } hl = highlight(day, month, year, start_day, start_month, start_year, nights, working, weekday, numdays); printf("",highlights[0][hl],day,highlights[1][hl]); if (col == 6) { printf("\n"); col = -1; } col++; } printf("\n"); pad(tab); printf("
   %s %d
SuMoTuWeThFrSa
"); printf("
%s%d%s
\n"); return 0; } int makesched(char values[NUMVALUES][MAXBUF]) { time_t rawtime; struct tm * curtime; int cur_month, cur_year, cur_day, month, year, nights, working, weekday; int numdays[12]={31,28,31,30,31,30,31,31,30,31,30,31}; char *endptr; time (&rawtime); curtime = localtime(&rawtime); cur_month = curtime->tm_mon; cur_year = curtime->tm_year + 1900; cur_day = curtime->tm_mday; weekday = curtime->tm_wday; // figure out target schedule // this month if (strcmp(values[3],"Current")==0) { month = cur_month; year = cur_year; } // next month else if (strcmp(values[3],"Next")==0) { month = cur_month + 1; year = cur_year; if (month == 12) { month = 0; year++; } } else { year = strtol(values[4], &endptr, 10); // all months if (strcmp(values[3], "All") == 0) month = -1; // specific month else month = strtol(values[3], &endptr, 10) - 1; } // check for leapyear if (leapyear(year) == 1) numdays[1] = 29; // check if we're working if (strcmp(values[1], "Yes") == 0) working = 1; else working = 0; // check if we're on nights if (strcmp(values[2], "Nights") == 0) nights = 1; else nights = 0; // if we're just printing one month if (month != -1) printmonth(month, year, cur_day, cur_month, cur_year, nights, working, weekday, numdays, 2); // the whole year else { for (month = 0; month < 12; month++) { if (month % 3 == 0) { pad(2); printf("\n"); pad(3); printf("\n"); pad(4); printf("\n"); pad(4); printf("\n"); pad(4); printf("\n"); pad(3); printf("\n"); pad(2); printf("
\n"); printmonth(month, year, cur_day, cur_month, cur_year, nights, working, weekday, numdays, 5); pad(4); printf("\n"); } else if (month % 3 == 1) { printmonth(month, year, cur_day, cur_month, cur_year, nights, working, weekday, numdays, 5); pad(4); printf("\n"); } else { printmonth(month, year, cur_day, cur_month, cur_year, nights, working, weekday, numdays, 5); pad(4); printf("
\n"); } } } return 0; } int getvalues(const char buff[MAXBUF], const char *endptr, char targets[NUMVALUES][MAXNAMELEN], char values[NUMVALUES][MAXBUF]) { char *start; char *end; char *ptr; int i; int len; for (i = 0; i < NUMVALUES; i++) { // search for the target string position start = strstr(buff,(char *)targets[i]); // start is the target pos + length of target name start = start + strlen((char *)targets[i]); // end is the first & after start end = strchr(start,'&'); // if no & is found then len is the end of meaningful buff contents - start if (end == NULL) len = endptr - start; // else len = pos of & - start else len = end - start; // copy appropriate len bytes from buff to values memcpy(values[i],start,len); values[i][len]='\0'; } return 0; }