/************************************************************************************ * * Reports Wizard * * Program to keep track of class information--including payment, attendance and * progress--generating report files for individual students. * * Program: reports_wizard * Author : yetimach * Date : 24 Sep 2022 * ************************************************************************************/ #include #include #include #include #include #define MAX_WORD 50 #define MAX_TEXT 100 #define EXTRA 10 #define MAX_REC 10000 #define MAX_NUM_CH 10 #define DATE 10 #define RATE 40 #define MAX_OPTS 4 #define DELAY 500 #define RECORD_CLASS 0 #define RECORD_PAYMENT 1 #define GEN_NEW_REPORT 2 #define QUIT 3 FILE *student_info; struct student { char first_name[MAX_WORD]; char last_name[MAX_WORD]; char access_code[MAX_WORD]; // to access file with command line arg. // Could just be first name, but there may // be multiple students with same first name. char level[MAX_WORD]; char schedule[MAX_TEXT]; char comment[MAX_TEXT]; int payment; int classes_taken; int classes_paid; char prev_classes[MAX_REC]; char last_progress[MAX_TEXT]; }; struct student st; void bomb(char *msg){ endwin(); puts(msg); exit(1); } int read_int(){ int ch, count = 0, i = 0; char temp_num_str[MAX_NUM_CH]; char num_str[MAX_NUM_CH]; getnstr(temp_num_str, MAX_NUM_CH); // if user leavs feild blank just record a 0 if (temp_num_str[0] == '\0') return 0; while (!isdigit(ch = temp_num_str[i++])) ; num_str[count++] = ch; while (isdigit(num_str[count++] = temp_num_str[i++])) ; num_str[count] = '\0'; return atoi(num_str); } void record_info(){ char st_info_fn[MAX_WORD + EXTRA]; strcpy(st_info_fn, st.access_code); strcat(st_info_fn, "_info"); student_info = fopen(st_info_fn, "w"); fprintf(student_info, "\n\n\tStudent Information" "\n\n\tName.........: %s %s" "\n\tAccess code..: %s" "\n\tLevel........: %s" "\n\tSchedule.....: %s" "\n\tPayment......: %d PEN" "\n\tClasses paid.: %d" "\n\tClasses taken: %d" "\n\tLast progress: %s" "\t%s", st.first_name, st.last_name, st.access_code, st.level, st.schedule, st.payment, st.classes_paid, st.classes_taken, st.last_progress, st.prev_classes); fclose(student_info); return; } void go_to_colon(){ int c; while ((c = getc(student_info)) != ':' && c != EOF) ; // do nothing getc(student_info); // eat the space return; } void read_info(){ int c, pos = 0; go_to_colon(); fscanf(student_info, "%s %s", st.first_name, st.last_name); go_to_colon(); fscanf(student_info, "%s", st.access_code); go_to_colon(); fscanf(student_info, "%[^\n]", st.level); go_to_colon(); fscanf(student_info, "%[^\n]", st.schedule); go_to_colon(); fscanf(student_info, "%d", &st.payment); go_to_colon(); fscanf(student_info, "%d", &st.classes_paid); go_to_colon(); fscanf(student_info, "%d", &st.classes_taken); go_to_colon(); fscanf(student_info, "%[^\n]", st.last_progress); while ((c = getc(student_info)) != EOF){ st.prev_classes[pos++] = c; if (pos >= MAX_REC - 1){ printf("\n\tError: Attendance record excedes maximum length.\n"); break; } } st.prev_classes[pos] = '\0'; return; } void cpy_none_if_empty(char *str){ if (str[0] == '\0') strcpy(str, "None"); } void create_new_profile(){ attron(A_BOLD); printw("\n\tReports Wizard\n"); attroff(A_BOLD); printw("\n\n\tCreate new profile" "\n\n\tFirst name: "); refresh(); getnstr(st.first_name, MAX_WORD); cpy_none_if_empty(st.first_name); printw("\n\tLast name: "); refresh(); getnstr(st.last_name, MAX_WORD); cpy_none_if_empty(st.last_name); printw("\n\tAccess code: "); refresh(); getnstr(st.access_code, MAX_WORD); cpy_none_if_empty(st.access_code); printw("\n\tLevel: "); refresh(); getnstr(st.level, MAX_TEXT - 1); cpy_none_if_empty(st.level); printw("\n\tSchedule: "); refresh(); getnstr(st.schedule, MAX_TEXT - 1); cpy_none_if_empty(st.schedule); st.payment = 0; st.classes_paid = 0; st.classes_taken = 0; strcpy(st.prev_classes, "\n\n\tAttendance Record\n"); strcpy(st.last_progress, "None"); return; } void print_st_info(){ attron(A_BOLD); printw("\n\n\tReports Wizard"); attroff(A_BOLD); printw("\n\n\tStudent Information"); printw("\n\n\tName.........: %s %s" "\n\tAccess code..: %s" "\n\tLevel........: %s" "\n\tSchedule.....: %s" "\n\tPayment......: %d PEN" "\n\tClasses paid.: %d" "\n\tClasses taken: %d" "\n\tLast progress: %s\n\t", st.first_name, st.last_name, st.access_code, st.level, st.schedule, st.payment, st.classes_paid, st.classes_taken, st.last_progress); refresh(); return; } void record_class(char *file_name, FILE *file){ int count = 0; // generate date string FILE *date_file; char date[DATE]; char command[MAX_TEXT] = "date +%D > date_file"; system(command); date_file = fopen("date_file", "r"); while ((date[count++] = getc(date_file)) != ' ' && date[count -1] != '\n') ; //read the date into string date[count] = '\0'; count = 0; fclose(date_file); char notes[MAX_TEXT]; erase(); print_st_info(); printw("\n\tNotes: "); refresh(); getnstr(notes, MAX_TEXT); strcpy(st.last_progress, notes); ++st.classes_taken; record_info(); strcat(command, file_name); file = fopen(file_name, "a"); fprintf(file, "\n\t%d. Class taken on %s", st.classes_taken, date); fprintf(file, "\t %s", notes); fclose(file); printw("\n\tClass recorded.\n\n"); refresh(); napms(DELAY); return; } void record_payment(){ erase(); print_st_info(); printw("\n\tEnter amount in PEN: "); refresh(); st.payment += read_int(); st.classes_paid = st.payment / RATE; record_info(); endwin(); printw("\n\tPayment recorded.\n\n"); refresh(); napms(DELAY); return; } int sure(){ char sures[2]; printw("\n\tAre you sure? [Y/n] "); refresh(); getnstr(sures, 1); if (sures[0] == '\0') return TRUE; if (tolower(sures[0]) == 'y') return TRUE; return FALSE; } void gen_new(char *file_name, FILE *file){ char command[MAX_TEXT] = "cp "; strcat(command, file_name); strcat(command, " old_"); strcat(command, file_name); system(command); st.payment = 0; st.classes_paid = 0; st.classes_taken = 0; strcpy(st.prev_classes, "\n\n\tAttendance Record\n"); file = fopen(file_name, "w"); record_info(); fclose(file); endwin(); printw("\n\tNew report generated. Old report saved as old_%s.\n\n", file_name); refresh(); napms(DELAY); return; } void draw_menu(int item){ int c; clrtobot(); char menu[MAX_OPTS][MAX_WORD] = { "record class", "record payment", "generate new report", "quit" }; for (c = 0; c < MAX_OPTS; c++){ if (c == item) attron(A_REVERSE); /* highlight selection */ mvaddstr(15+(c),8,menu[c]); attroff(A_REVERSE); /* remove highlight */ } } int print_and_read_opts(){ erase(); print_st_info(); // refresh(); int key, menuitem; menuitem = RECORD_CLASS; draw_menu(menuitem); keypad(stdscr, TRUE); noecho(); do { key = getch(); switch(key){ case 'j': case KEY_DOWN: menuitem++; if (menuitem > MAX_OPTS - 1) menuitem = 0; break; case 'k': case KEY_UP: menuitem--; if (menuitem < 0) menuitem = MAX_OPTS - 1; break; default: break; } draw_menu(menuitem); }while (key != '\n'); echo(); return menuitem; } int process_opts(int mi, char *st_info_fn){ switch (mi) { case RECORD_CLASS: record_class(st_info_fn, student_info); return 1; case RECORD_PAYMENT: record_payment(); return 1; case GEN_NEW_REPORT: erase(); print_st_info(); refresh(); if (sure()) gen_new(st_info_fn, student_info); else { addstr("\n\tNothing was done."); refresh(); napms(DELAY); } return 1; case QUIT: return 0; } return 0; } int print_and_process_opts(char *st_info_fn){ int selection = print_and_read_opts(st_info_fn); return process_opts(selection, st_info_fn); } int main(int argc, char *argv[]) { if (argc != 2){ printf("\n\tUsage: reports_wizard " "\n\t Ex: reports_wizard johnp" "\n\n\tTo create a new profile, provide the argument \"new\"." "\n\t Ex: reports_wizard new\n\n"); return 0; }else{ bool new_profile = FALSE, use_colors = FALSE; initscr(); if (has_colors() == TRUE) if (start_color() == 0) use_colors = TRUE; if (use_colors){ // set text to black and window background to white start_color(); init_pair(1, COLOR_BLACK, COLOR_WHITE); bkgd(COLOR_PAIR(1)); } if (strcmp(argv[1], "new") == 0){ new_profile = TRUE; create_new_profile(); record_info(); printw("\n\tProfile created for %s %s\n\n" "\n\tAccess code is: %s\n\n", st.first_name, st.last_name, st.access_code); refresh(); } char student_info_fn[MAX_WORD + EXTRA]; // file name if (!new_profile){ strcpy(student_info_fn, argv[1]); strcat(student_info_fn, "_info"); }else{ strcpy(student_info_fn, st.access_code); strcat(student_info_fn, "_info"); } // make sure name is valid if( access( student_info_fn, F_OK ) == -1 ) { printf("\n\tError: \"%s\" is not a valid access code.\n\n", argv[1]); endwin(); return 0; } // assign names to file pointers and open them for specific student student_info = fopen(student_info_fn, "r"); read_info(); if (!new_profile){ attron(A_BOLD); printw("\n\tReports Wizard\n"); refresh(); attroff(A_BOLD); } while (print_and_process_opts(student_info_fn)){ napms(DELAY); erase(); } } printw("\n\n\tGoodbye\n\n"); refresh(); napms(DELAY); endwin(); return 0; }