#include #include #include #include #include #include #include #include #include "global.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_file_util.h" #include "manhat-lib/shared_person_list.h" #include "manhat-lib/shared_super_key.h" #include "manhat-lib/shared_course_search.h" typedef enum {DISK_USAGE, MSG_COUNT, WEBSITE_COUNT, FILE_COUNT, STUDENT_COUNT, CHAT_MSG_COUNT} SORTS; typedef struct group_summary { int classroom_count; double disk_usage; double average_disk_usage; double median_disk_usage; double msg_disk_usage; double file_disk_usage; double website_disk_usage; double misc_disk_usage; int msg_count; double median_msg_count; int website_count; double median_website_count; int file_count; double median_file_count; int chat_msg_count; double median_chat_msg_count; int student_count; double median_student_count; CONFIG_STRUCT conf; } GROUP_SUMMARY; typedef struct module_node { char module_name[MAX_FILENAME + 1]; double disk_usage; double msg_disk_usage; double file_disk_usage; double website_disk_usage; double misc_disk_usage; int msg_count; int website_count; int file_count; struct module_node *next; } MODULE_NODE; typedef struct course_node { char dirname[MAX_FILENAME + 1]; CONFIG_STRUCT conf; int teacher_count; int student_count; double disk_usage; double msg_disk_usage; double file_disk_usage; double website_disk_usage; double misc_disk_usage; int msg_count; int chat_msg_count; int file_count; int website_count; MODULE_NODE *module_head; struct course_node *next; } COURSE_NODE; COURSE_NODE *course_head = (COURSE_NODE *) 0; static void read_parameters (char *key, char *group) { cs_get_required_parameter("id", key, MAX_KEY); cs_get_required_parameter("subdir", group, MAX_FILENAME); } static void my_crash(const char *msg) { puts(msg); puts("\n\n"); exit(1); } void *my_malloc(size_t size) { void *ptr; ptr = malloc(size); if(!ptr) my_crash("malloc() failed"); return ptr; } static void my_strncpy(char *dest, char *src, int len) { strncpy(dest, src, len); *(dest + len - 1) = '\0'; } static COURSE_NODE * new_course_node(char *group_dir, char *course_dir) { COURSE_NODE *ptr; char course_name[MAX_PATH + 1]; CONFIG_STRUCT conf; P_NODE *person_head; snprintf(course_name, MAX_PATH + 1, "%s%s/%s", COURSE_PATH, group_dir, course_dir); if(!read_configuration_file_ok(course_name, &conf)) /* shared_util.c */ return (COURSE_NODE *) 0; if(!course_head) { course_head = (COURSE_NODE *) my_malloc(sizeof(COURSE_NODE)); ptr = course_head; } else { for(ptr = course_head; ptr->next; ptr=ptr->next); ptr->next = my_malloc(sizeof(COURSE_NODE)); ptr = ptr->next; } my_strncpy(ptr->dirname, course_dir, MAX_FILENAME + 1); ptr->conf = conf; person_head = build_option_person_list(&conf); /* shared_person_list.c */ ptr -> teacher_count = count_faculty(person_head); /* shared_person_list.c */ ptr -> student_count = count_students(person_head); /* shared_person_list.c */ free_option_person_list(person_head); /* shared_person_list.c */ ptr->disk_usage = 0; ptr->msg_disk_usage = 0; ptr->file_disk_usage = 0; ptr->website_disk_usage = 0; ptr->misc_disk_usage = 0; ptr->msg_count = 0; ptr->chat_msg_count = 0; ptr->file_count = 0; ptr->website_count = 0; ptr->module_head = (MODULE_NODE *) 0; ptr -> next = (COURSE_NODE *) 0; return ptr; } static MODULE_NODE * find_module_node (COURSE_NODE *course_ptr, char *module_name) { MODULE_NODE *module_ptr; int found; if(!course_ptr->module_head) { course_ptr->module_head = (MODULE_NODE *) my_malloc(sizeof(MODULE_NODE)); module_ptr = course_ptr->module_head; found = 0; } else { for(found = 0, module_ptr = course_ptr->module_head; module_ptr->next; module_ptr=module_ptr->next) { found = !strcmp(module_name, module_ptr->module_name); if(found) break; } if(!found) { module_ptr->next = (MODULE_NODE *) my_malloc(sizeof(MODULE_NODE)); module_ptr = module_ptr -> next; } } if(!found) { my_strncpy(module_ptr->module_name, module_name, MAX_FILENAME + 1); module_ptr -> disk_usage = 0; module_ptr -> msg_disk_usage = 0; module_ptr -> file_disk_usage = 0; module_ptr -> website_disk_usage = 0; module_ptr -> misc_disk_usage = 0; module_ptr -> msg_count = 0; module_ptr -> website_count = 0; module_ptr -> file_count = 0; module_ptr -> next = (MODULE_NODE *) 0; } return module_ptr; } static long file_size(char *dir, char *fname) { char path[MAX_PATH + 1]; struct stat buf; snprintf(path, MAX_PATH + 1, "%s/%s", dir, fname); if(!stat(path, &buf)) // && !(S_ISDIR (buf.st_mode)) ) return (long) buf.st_size; else return (long) 0; } static long dir_size(char *dir, char *fname) { char *path, *filepath; DIR *dir_p; struct dirent *dir_entry_p; long filesize = 0; struct stat buf; int malloc_size; malloc_size = strlen(dir) + strlen(fname) + 10; path = (char *) my_malloc(malloc_size); filepath = (char *) my_malloc(malloc_size + MAX_PATH); sprintf(path, "%s/%s", dir, fname); dir_p = opendir (path); if (dir_p) { filesize += file_size(path, "."); /* count size of the directory entry itself */ while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { snprintf(filepath, malloc_size + MAX_PATH, "%s/%s", path, dir_entry_p->d_name); if(!stat(filepath, &buf)) { if(S_ISDIR (buf.st_mode)) filesize += dir_size(path, dir_entry_p->d_name); else filesize += (long) buf.st_size; } } } closedir(dir_p); } free(path); free(filepath); return filesize; } /** Need to find filenames of the form "msg_xxxxxx" and "xxxxxx.msg" *** and "fil_xxxxxx" and "xxxxxxx.fil" and so on. *** *** Using 'msg' as an example, ptr points to substring 'msg' in larger *** null-terminated string 'string'. 'len' is the string length of 'msg'. *** *** does string either start with msg_ or end with .msg ? **/ static int starts_ends_with(char *target, char *string) { int len = strlen(target); char *ptr; ptr = strstr(string, target); if(ptr) return ((ptr == string) && (*(ptr + len) == '_') ) || ( (*(ptr - 1) == '.') && (*(ptr + len) == '\0') ); else return 0; } static void count_user_module_usage(COURSE_NODE *course_ptr, char *module_dir, char *user_path) { char module_path[MAX_PATH + 1]; MODULE_NODE *module_ptr; DIR *dir_p; struct dirent *dir_entry_p; long filesize; snprintf(module_path, MAX_PATH + 1, "%s/%s", user_path, module_dir); dir_p = opendir (module_path); if (dir_p) { module_ptr = find_module_node(course_ptr, module_dir); course_ptr->misc_disk_usage += file_size(module_path, "."); /* count size of this module directory */ while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { if(starts_ends_with("msg", dir_entry_p->d_name)) { module_ptr -> msg_count++; filesize = file_size(module_path, dir_entry_p->d_name); module_ptr -> msg_disk_usage += filesize; } else if(starts_ends_with("fil",dir_entry_p->d_name)) { module_ptr -> file_count++; filesize = file_size(module_path, dir_entry_p->d_name); module_ptr -> file_disk_usage += filesize; } else if(starts_ends_with("dir", dir_entry_p->d_name) || /* attached website */ starts_ends_with("hot", dir_entry_p->d_name) ) /* attached hot exam in assign module */ { module_ptr -> website_count++; filesize = dir_size(module_path, dir_entry_p->d_name); module_ptr->website_disk_usage += filesize; } else /* misc. files, e.g. 'inf' files, filter.dat, inbox.dat, last_gather.dat, etc ... */ { filesize = file_size(module_path, dir_entry_p->d_name); module_ptr->misc_disk_usage += filesize; } module_ptr -> disk_usage += filesize; /* update total */ } } closedir (dir_p); } else /* might have found a regular file in this user's directory - such as access_log.dat */ course_ptr->misc_disk_usage += file_size(user_path, module_dir); } static void analyze_user(char *people_dir, char *user_dir, COURSE_NODE *course_ptr) { char path[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; snprintf(path, MAX_PATH + 1, "%s/%s", people_dir, user_dir); dir_p = opendir (path); if (dir_p) { course_ptr->misc_disk_usage += file_size(path, "."); /* count size of this user's directory as 'misc_disk_usage */ while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { count_user_module_usage(course_ptr,dir_entry_p->d_name, path); } } closedir(dir_p); } } static void update_module_totals(COURSE_NODE *course_ptr) { MODULE_NODE *module_ptr; for(module_ptr = course_ptr->module_head; module_ptr; module_ptr = module_ptr->next) { course_ptr->disk_usage += module_ptr->disk_usage; course_ptr->msg_disk_usage += module_ptr->msg_disk_usage; course_ptr->file_disk_usage += module_ptr -> file_disk_usage; course_ptr->website_disk_usage += module_ptr -> website_disk_usage; course_ptr->misc_disk_usage += module_ptr->misc_disk_usage; course_ptr->msg_count += module_ptr->msg_count; course_ptr->website_count += module_ptr->website_count; course_ptr->file_count += module_ptr->file_count; } } /* This code taken from chat_transcript.c */ static void count_chat_msgs(COURSE_NODE *course_ptr, char *group_dir, char *course_dir) { FILE *fp; char path[MAX_PATH + 1]; time_t msg_time; /* the CHAT_MSG_LOG has these data items in this order */ int deleted; char sender[40]; int msg_len; char *msg = (char *) 0; course_ptr->chat_msg_count = 0; snprintf (path, MAX_PATH + 1, "%s%s/%s/%s", COURSE_PATH, group_dir, course_dir, CHAT_MSG_LOG); fp = fopen (path, "r"); if (!fp) return; while (fread (&msg_time, sizeof (time_t), 1, fp) == 1) { /* was this message deleted by the teacher ? */ if (fread (&deleted, sizeof (int), 1, fp) != 1) break; /* who typed the message (realname) **/ if (fread (sender, 40 * sizeof (char), 1, fp) != 1) break; /* how many chars were typed - what is the length of the message? */ if (fread (&msg_len, sizeof (int), 1, fp) != 1) break; /** allocate space for the 'raw' message **/ msg = (char *) my_malloc ((msg_len + 1) * sizeof (char)); /* read the raw message */ if ((int)fread (msg, sizeof (char), msg_len, fp) != msg_len) break; msg[msg_len] = '\0'; /* need to escape html chars */ if(msg) { free (msg); msg = (char *) 0; } course_ptr->chat_msg_count++; } fclose (fp); } static void count_misc_course_data(COURSE_NODE *course_ptr, char *group_dir, char *course_dir) { char path[MAX_PATH + 1]; char filepath[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; struct stat buf; snprintf(path, MAX_PATH + 1, "%s%s/%s", COURSE_PATH, group_dir, course_dir); dir_p = opendir (path); if (dir_p) { course_ptr->misc_disk_usage += file_size(path, "."); /* count size of THIS course directory */ while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..") && strcmp (dir_entry_p->d_name, "people") ) /* since the people directory has already been dealt with */ { snprintf(filepath, MAX_PATH + 1, "%s/%s", path, dir_entry_p->d_name); if(!stat(filepath, &buf)) { if (S_ISDIR(buf.st_mode)) { course_ptr->misc_disk_usage += dir_size(path, dir_entry_p->d_name); } else { course_ptr->misc_disk_usage += buf.st_size; } } } } closedir(dir_p); } } static void update_total_disk_usage(COURSE_NODE *course_ptr) { course_ptr->disk_usage = course_ptr->msg_disk_usage + course_ptr->file_disk_usage + course_ptr->website_disk_usage + course_ptr->misc_disk_usage; } static void analyze_course(char *group_dir, char *course_dir) { char path[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; COURSE_NODE *course_ptr; static int count = 0; snprintf(path, MAX_PATH + 1, "%s%s/%s/%s", COURSE_PATH, group_dir, course_dir, PEOPLE_DIR); dir_p = opendir (path); if (dir_p) { course_ptr = new_course_node(group_dir, course_dir); if(course_ptr) { count++; printf("%s ", course_dir); if(!(count % 10)) printf("\n"); fflush(stdout); course_ptr -> misc_disk_usage += file_size(path, "."); /* count size of the 'people' directory */ while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { analyze_user(path, dir_entry_p->d_name, course_ptr); } } update_module_totals(course_ptr); count_chat_msgs(course_ptr, group_dir, course_dir); count_misc_course_data(course_ptr,group_dir, course_dir); update_total_disk_usage(course_ptr); } closedir (dir_p); } } static void clear_summary(GROUP_SUMMARY *summary) { summary->classroom_count = 0; summary->disk_usage = 0; summary->average_disk_usage = 0.0; summary->median_disk_usage = 0.0; summary->msg_disk_usage = 0; summary->file_disk_usage = 0; summary->website_disk_usage = 0; summary->misc_disk_usage = 0; summary->msg_count = 0; summary->median_msg_count = 0; summary->website_count = 0; summary->median_website_count = 0; summary->file_count = 0; summary->median_file_count = 0; summary->chat_msg_count = 0; summary->median_chat_msg_count = 0; summary->student_count = 0; summary->median_student_count = 0; summary->conf.assignments = 0; summary->conf.syllabus = 0; summary->conf.discussion = 0; summary->conf.postoffice = 0; summary->conf.internet = 0; summary->conf.lounge = 0; summary->conf.chat = 0; summary->conf.anonymous = 0; summary->conf.team = 0; summary->conf.team_teach = 0; summary->conf.grades = 0; summary->conf.selftest = 0; summary->conf.lectures = 0; summary->conf.people = 0; summary->conf.surveys = 0; summary->conf.podcasts = 0; } static void add_to_summary(COURSE_NODE *course_ptr, GROUP_SUMMARY *summary) { summary->classroom_count++; summary->disk_usage += course_ptr->disk_usage;; summary->msg_disk_usage += course_ptr->msg_disk_usage; summary->file_disk_usage += course_ptr->file_disk_usage; summary->website_disk_usage += course_ptr->website_disk_usage; summary->misc_disk_usage += course_ptr->misc_disk_usage; summary->msg_count += course_ptr->msg_count; summary->website_count += course_ptr->website_count; summary->file_count += course_ptr -> file_count; summary->chat_msg_count += course_ptr->chat_msg_count; summary->student_count += course_ptr->student_count; if(course_ptr->conf.assignments) summary->conf.assignments++; if(course_ptr->conf.syllabus) summary->conf.syllabus++; if(course_ptr->conf.discussion) summary->conf.discussion++; if(course_ptr->conf.postoffice) summary->conf.postoffice++; if(course_ptr->conf.internet) summary->conf.internet++; if(course_ptr->conf.lounge) summary->conf.lounge++; if(course_ptr->conf.chat) summary->conf.chat++; if(course_ptr->conf.anonymous) summary->conf.anonymous++; if(course_ptr->conf.team) summary->conf.team++; if(course_ptr->conf.team_teach) summary->conf.team_teach++; if(course_ptr->conf.grades) summary->conf.grades++; if(course_ptr->conf.selftest) summary->conf.selftest++; if(course_ptr->conf.lectures) summary->conf.lectures++; if(course_ptr->conf.people) summary->conf.people++; if(course_ptr->conf.surveys) summary->conf.surveys++; if(course_ptr->conf.podcasts) summary->conf.podcasts++; } static int course_node_cmp( COURSE_NODE *a, COURSE_NODE *b, SORTS sort) { if(sort == MSG_COUNT) { if(a->msg_count > b->msg_count) return -1; else if(a->msg_count < b->msg_count) return +1; else return 0; } else if(sort == WEBSITE_COUNT) { if(a->website_count > b->website_count) return -1; else if(a->website_count < b->website_count) return +1; else return 0; } else if(sort == FILE_COUNT) { if(a->file_count > b->file_count) return -1; else if(a->file_count < b->file_count) return +1; else return 0; } else if(sort == STUDENT_COUNT) { if(a->student_count > b->student_count) return -1; else if(a->student_count < b->student_count) return +1; else return 0; } else if(sort == CHAT_MSG_COUNT) { if(a->chat_msg_count > b->chat_msg_count) return -1; else if(a->chat_msg_count < b->chat_msg_count) return +1; else return 0; } else /* sort == DISK_USAGE */ { if(a->disk_usage > b->disk_usage) return -1; else if(a->disk_usage < b->disk_usage) return +1; else return 0; } } static COURSE_NODE * sort_course_list (COURSE_NODE *course_head, SORTS sort) { COURSE_NODE *q, *tail, *p, *r; if (course_head != NULL) { tail = course_head; while (tail->next) { q = tail->next; if (course_node_cmp (q, course_head, sort) < 0) { tail->next = q->next; q->next = course_head; course_head = q; } else { r = course_head; p = r->next; while (course_node_cmp (q,p, sort) > 0) { r = p; p = r->next; } if (q == p) tail = q; else { tail->next = q->next; q->next = p; r->next = q; } } } } return course_head; } static void get_median_disk_usage(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, DISK_USAGE); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> disk_usage; if(median_requires_average && (ptr->next)) result = (result + ptr->next->disk_usage) / 2.0; } summary->median_disk_usage = result; } static void get_median_msg_count(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, MSG_COUNT); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> msg_count; if(median_requires_average && (ptr->next)) result = (result + ptr->next->msg_count) / 2.0; } summary->median_msg_count = result; } static void get_median_website_count(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, WEBSITE_COUNT); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> website_count; if(median_requires_average && (ptr->next)) result = (result + ptr->next->website_count) / 2.0; } summary->median_website_count = result; } static void get_median_file_count(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, FILE_COUNT); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> file_count; if(median_requires_average && (ptr->next)) result = (result + ptr->next->file_count) / 2.0; } summary->median_file_count = result; } static void get_median_student_count(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, STUDENT_COUNT); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> student_count; if(median_requires_average && (ptr->next)) result = (result + ptr->next->student_count) / 2.0; } summary->median_student_count = result; } static void get_median_chat_msg_count(GROUP_SUMMARY *summary, int middle, int median_requires_average) { COURSE_NODE *ptr; int i; double result = 0.0; course_head = sort_course_list(course_head, CHAT_MSG_COUNT); for(i=1, ptr=course_head; (i < middle) && ptr; ptr=ptr->next, i++); if(ptr) { result = ptr -> chat_msg_count; if(median_requires_average && (ptr->next)) result = (result + ptr->next->chat_msg_count) / 2.0; } summary->median_chat_msg_count = result; } static void find_middle(int count, int *middle, int *median_requires_average) { if(count <= 1) { *middle = count; *median_requires_average = 0; } else { *middle = count / 2; if( count % 2) /* if odd */ { *middle++; *median_requires_average = 0; } else { *median_requires_average = 1; } } } static void summarize_group(GROUP_SUMMARY *summary) { COURSE_NODE *ptr; int middle; int median_requires_average; clear_summary(summary); for(ptr=course_head; ptr; ptr=ptr->next) add_to_summary(ptr, summary); summary->average_disk_usage = summary->disk_usage / (double) summary->classroom_count; find_middle(summary->classroom_count, &middle, &median_requires_average); get_median_disk_usage(summary, middle, median_requires_average); get_median_msg_count(summary, middle, median_requires_average); get_median_website_count(summary, middle, median_requires_average); get_median_file_count(summary, middle, median_requires_average); get_median_student_count(summary, middle, median_requires_average); get_median_chat_msg_count(summary, middle, median_requires_average); } static void analyze_course_group(char *group, GROUP_SUMMARY *summary) { char path[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; printf("Analyzing course group: %s ...\n", group); snprintf(path, MAX_PATH + 1,"%s%s", COURSE_PATH, group); dir_p = opendir (path); if (!dir_p) { perror("Unable to open group directory, so quitting"); my_crash("Unable to open group directory, so quitting. Bye!"); } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { analyze_course(group, dir_entry_p->d_name); } } closedir (dir_p); if(!course_head) { my_crash("No courses found.\n. Bye!"); } printf("\n\nSummarizing... "); fflush(stdout); summarize_group(summary); course_head = sort_course_list(course_head, DISK_USAGE); } static void write_one_course_hdf (FILE *fp, COURSE_NODE *course_ptr) { static int course_no = 0; char number_string[25]; MODULE_NODE *mptr; fprintf(fp, "class.%d.dir = %s\n", course_no, course_ptr->dirname); fprintf(fp, "class.%d.course_no = %s\n", course_no, course_ptr->conf.course_no); fprintf(fp, "class.%d.title = %s\n", course_no, course_ptr->conf.title); fprintf(fp, "class.%d.semester = %s\n", course_no, course_ptr->conf.semester); fprintf(fp, "class.%d.instructor = %s\n", course_no, course_ptr->conf.instructor); fprintf(fp, "class.%d.teachers = %d\n", course_no, course_ptr->teacher_count); fprintf(fp, "class.%d.students = %d\n", course_no, course_ptr->student_count); strfmon(number_string, 24, "%!.0n", (double)course_ptr->disk_usage); fprintf(fp, "class.%d.disk_usage = %s\n", course_no, number_string); strfmon(number_string, 24, "%!.0n", (double)course_ptr->msg_disk_usage); fprintf(fp, "class.%d.msg_disk_usage = %s\n", course_no, number_string); strfmon(number_string, 24, "%!.0n", (double)course_ptr->file_disk_usage); fprintf(fp, "class.%d.file_disk_usage = %s\n", course_no, number_string); strfmon(number_string, 24, "%!.0n", (double)course_ptr->website_disk_usage); fprintf(fp, "class.%d.website_disk_usage = %s\n", course_no, number_string); strfmon(number_string, 24, "%!.0n", (double)course_ptr->misc_disk_usage); fprintf(fp, "class.%d.misc_disk_usage = %s\n", course_no, number_string); fprintf(fp, "class.%d.msg_count = %d\n", course_no, course_ptr->msg_count); fprintf(fp, "class.%d.chat_msg_count = %d\n", course_no, course_ptr->chat_msg_count); fprintf(fp, "class.%d.file_count = %d\n", course_no, course_ptr->file_count); fprintf(fp, "class.%d.website_count = %d\n", course_no, course_ptr->website_count); for(mptr=course_ptr->module_head; mptr; mptr=mptr->next) { strfmon(number_string, 24, "%!.0n", (double)mptr->disk_usage); fprintf(fp, "class.%d.module.%s.disk_usage = %s\n", course_no, mptr->module_name, number_string); strfmon(number_string, 24, "%!.0n", (double)mptr->msg_disk_usage); fprintf(fp, "class.%d.module.%s.msg_disk_usage = %s\n", course_no, mptr->module_name, number_string); strfmon(number_string, 24, "%!.0n", (double)mptr->file_disk_usage); fprintf(fp, "class.%d.module.%s.file_disk_usage = %s\n", course_no, mptr->module_name, number_string); strfmon(number_string, 24, "%!.0n", (double)mptr->website_disk_usage); fprintf(fp, "class.%d.module.%s.website_disk_usage = %s\n", course_no, mptr->module_name, number_string); strfmon(number_string, 24, "%!.0n", (double)mptr->misc_disk_usage); fprintf(fp, "class.%d.module.%s.misc_disk_usage = %s\n", course_no, mptr->module_name, number_string); fprintf(fp, "class.%d.module.%s.msg_count = %d\n", course_no, mptr->module_name, mptr->msg_count); fprintf(fp, "class.%d.module.%s.website_count = %d\n", course_no, mptr->module_name, mptr->website_count); fprintf(fp, "class.%d.module.%s.file_count = %d\n", course_no, mptr->module_name, mptr->file_count); } course_no++; } static void write_summary_hdf(FILE *fp, char *group, GROUP_SUMMARY *summary) { char group_description[MAX_FILENAME + 1]; char timestring[MAX_TIMESTRING + 1]; time_t now; char number_string[25]; now = time(NULL); strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT, localtime (&now)); fprintf(fp,"analysis_timestamp = %s\n", timestring); fprintf(fp,"group_internal_name = %s\n", group); get_short_group_description(group, group_description); /* shared_course_search.c */ fprintf(fp, "group_description = %s\n", group_description); fprintf(fp, "classroom_count = %d\n", summary->classroom_count); fprintf(fp,"\n"); strfmon(number_string, 24, "%!.0n", (double)summary->disk_usage); fprintf(fp, "disk_usage = %s\n", number_string); strfmon(number_string, 24, "%!.0n", summary->average_disk_usage); fprintf(fp, "avg_disk_usage = %s\n", number_string); strfmon(number_string, 24, "%!.0n", summary->median_disk_usage); fprintf(fp, "median_disk_usage = %s\n", number_string); fprintf(fp,"\n"); strfmon(number_string, 24, "%!.0n", (double)summary->msg_disk_usage); fprintf(fp, "msg_disk_usage = %s (%3.2f%%)\n", number_string, ((double) summary->msg_disk_usage/ (double)summary->disk_usage) * 100.0); strfmon(number_string, 24, "%!.0n", (double)summary->file_disk_usage); fprintf(fp, "file_disk_usage = %s (%3.2f%%)\n", number_string, ((double) summary->file_disk_usage/ (double)summary->disk_usage) * 100.0); strfmon(number_string, 24, "%!.0n", (double)summary->website_disk_usage); fprintf(fp, "website_disk_usage = %s (%3.2f%%)\n", number_string, ((double) summary->website_disk_usage/ (double)summary->disk_usage) * 100.0); strfmon(number_string, 24, "%!.0n", (double)summary->misc_disk_usage); fprintf(fp, "misc_disk_usage = %s (%3.2f%%)\n", number_string, ((double) summary->misc_disk_usage/ (double)summary->disk_usage) * 100.0); fprintf(fp,"\n"); fprintf(fp,"msg_count = %d\n", summary->msg_count); fprintf(fp,"avg_msg_count = %.2f\n", (double) summary->msg_count/ summary->classroom_count); fprintf(fp,"median_msg_count = %.2f\n", (double) summary->median_msg_count); fprintf(fp,"\n"); fprintf(fp, "website_count = %d\n", summary->website_count); fprintf(fp,"avg_website_count = %.2f\n", (double) summary->website_count/ summary->classroom_count); fprintf(fp,"median_website_count = %.2f\n", (double) summary->median_website_count); fprintf(fp,"\n"); fprintf(fp,"file_count = %d\n", summary->file_count); fprintf(fp,"avg_file_count = %.2f\n", (double) summary->file_count/ summary->classroom_count); fprintf(fp,"median_file_count = %.2f\n", (double) summary->median_file_count); fprintf(fp,"\n"); fprintf(fp,"chat_msg_count = %d\n", summary->chat_msg_count); fprintf(fp,"avg_chat_msg_count = %.2f\n", (double) summary->chat_msg_count / summary->classroom_count); fprintf(fp,"median_chat_msg_count = %.2f\n", (double) summary->median_chat_msg_count); fprintf(fp,"\n"); fprintf(fp,"student_count = %d\n", summary->student_count); fprintf(fp, "avg_student_count = %.2f\n", (double) summary->student_count/ summary->classroom_count); fprintf(fp,"median_student_count = %.2f\n", (double) summary->median_student_count); fprintf(fp,"\n"); fprintf(fp,"assignments = %d (%3.1f%%)\n", summary->conf.assignments, (double) (summary->conf.assignments/(double) summary->classroom_count)*100.0); fprintf(fp,"handouts_notices = %d (%3.1f%%)\n", summary->conf.syllabus, (double) (summary->conf.syllabus/(double) summary->classroom_count)*100.0); fprintf(fp,"class_discussion = %d (%3.1f%%)\n", summary->conf.discussion, (double) (summary->conf.discussion/(double) summary->classroom_count)*100.0); fprintf(fp,"post_office = %d (%3.1f%%)\n", summary->conf.postoffice, (double) (summary->conf.postoffice/(double) summary->classroom_count)*100.0); fprintf(fp,"internet = %d (%3.1f%%)\n", summary->conf.internet, (double) (summary->conf.internet/(double) summary->classroom_count)*100.0); fprintf(fp,"lounge = %d (%3.1f%%)\n", summary->conf.lounge, (double) (summary->conf.lounge/(double) summary->classroom_count)*100.0); fprintf(fp,"chat = %d (%3.1f%%)\n", summary->conf.chat, (double) (summary->conf.chat/(double) summary->classroom_count)*100.0); fprintf(fp,"anonymous = %d (%3.1f%%)\n", summary->conf.anonymous, (double) (summary->conf.anonymous/(double) summary->classroom_count)*100.0); fprintf(fp,"team = %d (%3.1f%%)\n", summary->conf.team, (double) (summary->conf.team/(double) summary->classroom_count)*100.0); fprintf(fp,"team_teach = %d (%3.1f%%)\n", summary->conf.team_teach, (double) (summary->conf.team_teach/(double) summary->classroom_count)*100.0); fprintf(fp,"grades = %d (%3.1f%%)\n", summary->conf.grades, (double) (summary->conf.grades/(double) summary->classroom_count)*100.0); fprintf(fp,"selftest = %d (%3.1f%%)\n", summary->conf.selftest, (double) (summary->conf.selftest/(double) summary->classroom_count)*100.0); fprintf(fp,"lectures = %d (%3.1f%%)\n", summary->conf.lectures, (double) (summary->conf.lectures/(double) summary->classroom_count)*100.0); fprintf(fp,"people = %d (%3.1f%%)\n", summary->conf.people, (double) (summary->conf.people/(double) summary->classroom_count)*100.0); fprintf(fp,"surveys = %d (%3.1f%%)\n", summary->conf.surveys, (double) (summary->conf.surveys/(double) summary->classroom_count)*100.0); fprintf(fp,"podcasts = %d (%3.1f%%)\n", summary->conf.podcasts, (double) (summary->conf.podcasts/(double) summary->classroom_count)*100.0); fprintf(fp,"\n\n"); } static void write_hdf(char *group, GROUP_SUMMARY *summary) { FILE *fp; COURSE_NODE *ptr; char path[MAX_PATH + 1]; printf("Writing data... "); fflush(stdout); setlocale (LC_ALL, "en_US"); snprintf(path, MAX_PATH + 1, "%s%s/%s", COURSE_PATH, group, USAGE_REPORT_FNAME); fp = fopen(path, "w"); if(!fp) { perror(path); my_crash("Can't open file for writing."); } write_summary_hdf(fp, group, summary); for(ptr=course_head; ptr; ptr=ptr->next) write_one_course_hdf(fp, ptr); fclose(fp); puts(" Done!"); } static void free_course_list() { COURSE_NODE *ptr; MODULE_NODE *mptr; while(course_head) { ptr = course_head; course_head = course_head->next; while(ptr->module_head) { mptr = ptr->module_head; ptr->module_head = ptr->module_head->next; free(mptr); } free(ptr); } } int main() { char key[MAX_KEY + 1]; char group[MAX_FILENAME + 1]; SESSION user; GROUP_SUMMARY summary; cs_cgi_init(); read_parameters(key, group); cs_cgi_destroy(); validate_super_key(key, &user); puts("Content-type: text/html\n"); printf("\nAnalyzing course group\n"); puts("

Working ... Don't Interrupt!

Click the 'View Report' link, which will appear AT THE BOTTOM OF THIS PAGE, when the analysis is complete.

"); puts("
");

   analyze_course_group(group, &summary);
   write_hdf(group, &summary);
   puts("
"); printf("

View Report

", key, group); puts("\n"); free_course_list(); return 0; }