/***************************************************
    MT258 TMA02 q3d.cpp
    Question 3 (d) and (e)
    Analyzing student records    
    Programming by Allen Lam 99043953
    Dec 2000
****************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <mem.h>
#define SIZE 2048

/* A structure for holding student records */
struct TMARecord {
	char studentid[8];
	int   group;
	int	daysLate;
	int	articlesRead;
	int	articlesPosted;
};

struct TMARecord records[SIZE];  /* the actual store */
int recordCount = 0;             /* number of records currently in the store */
void printRecords();

/*****************************************************/
/*                 Question 3(d)                     */
/*               LateAndEarlyGroups                  */
/*****************************************************/
void LateAndEarlyGroups(struct TMARecord records[], int size){
  int i;
  int maxCount;        /* the maximum lateCount */
  struct GROUP{
    int daysLate;      /* no. of days late */
    int lateCount;     /* no. of students late */
    int studentCount;  /* no. of students in the group */
  }group[25];          /* group number 1 to 24 (group 0 is unused) */

  /* initialize the variables */
  for (i=0; i<=24; i++){
    group[i].daysLate = 0;
    group[i].lateCount = 0;
    group[i].studentCount = 0;
  }

  /* scan through the records */
  for (i=0; i<size; i++){
    group[records[i].group].studentCount++;
    if (records[i].daysLate>0){
      group[records[i].group].daysLate += records[i].daysLate;
      group[records[i].group].lateCount++;
    }
  }

  /* Find the max lateCount */
  maxCount = group[0].lateCount;
  for (i=1; i<=24; i++){
    if (group[i].lateCount>maxCount) maxCount = group[i].lateCount;
  }

  /* only display non-empty groups */
  clrscr();
  printf("TMA late submission analysis in each group\n\n");
  printf("Group\tNo. of late students\tAverage days late\t\n");
  for (i=0; i<=24; i++){
    if (group[i].studentCount>0)
      printf("%3d%15d%24.1f\n",
        i,
        group[i].lateCount,
        (float)group[i].daysLate/group[i].lateCount);
  }

  printf("\nGroup ");
  for (i=0; i<24; i++)
    if (group[i].lateCount==maxCount) printf("%d, ", i);
  printf("have the largest number of late submission students.\n\n");
}

/*****************************************************/
/*                 Question 3(d)                     */
/*               AnalyseDiscussion                   */
/*****************************************************/
void AnalyseDiscussion(struct TMARecord records[], int size) {
  int maxReadi;      /* index of student in records[] with max articlesRead */
  int maxPosti;      /* index of student in records[] with max articlesPost */
  int maxRead = 0;   /* store the max Read found */
  int maxPost = 0;   /* store the max Post found */
  int sumRead = 0;   /* sum of articles read by all students */
  int sumPost = 0;   /* sum of articles posted by all students */
  int i;

  maxRead = records[0].articlesRead;
  maxPost = records[0].articlesPosted;
  for (i=0; i<size; i++){
    /* find maxRead and maxReadi */
    if (records[i].articlesRead>maxRead){
      maxRead = records[i].articlesRead;
      maxReadi = i;
    }
    /* find maxPost and maxPosti */
    if (records[i].articlesPosted>maxPost){
      maxPost = records[i].articlesPosted;
      maxPosti = i;
    }
    /* find total read and posted */
    sumRead += records[i].articlesRead;
    sumPost += records[i].articlesPosted;
  }

  /* move cursor to the last line */
  gotoxy(1,25); cprintf("Press Enter for next page...");
  getchar(); clrscr();

  printf("Article reading and posting analysis\n\n");
  printf("* Student %s has read most articles (%d)\n", records[maxReadi].studentid, maxRead);
  printf("* Student %s has posted most articles (%d)\n\n", records[maxPosti].studentid, maxPost);
  printf("* All students have read articles %d times\n", sumRead);
  printf("* All students have posted articles %d times\n\n", sumPost);
  printf("* On average, each student has read %.1f articles\n", (float)sumRead/size);
  printf("* On average, each student has posted %.1f articles\n", (float)sumPost/size);
  /* move cursor to the last line */
  gotoxy(1,25); cprintf("Press Enter for next page...");
  getchar(); clrscr();
}

/*****************************************************/
/*                 Question 3(e)                     */
/*                AnalyseAdvanced                    */
/*****************************************************/

/* sort record[] based on articlesRead, in accending order */
int sortStruct(struct TMARecord rec[], int sizeofRec, int max){
  int i, j;
  void* tmp = malloc(sizeofRec);
  if (tmp==NULL) return 0;
  for (i=1; i<max; i++){
    for (j=max-1; j>=i; j--){
      if (rec[j].articlesRead<rec[j-1].articlesRead){
        /* swap records */
        memcpy(tmp, &rec[j], sizeofRec);
        memcpy(&rec[j], &rec[j-1], sizeofRec);
        memcpy(&rec[j-1], tmp, sizeofRec);
      }
    }
  }
  free(tmp);
  return 1;
}

/*
** The following two values determine the size and precision of the graph
*/
#define regX 15  /* X-axis divide into how many regions */
#define regY 15  /* Y-axis divide into how many regions */

void plot(int data[]){
  int x, y;                /* x and y coordinate on screen */
  int maxY, minY;          /* max & min value in y-data */
  float stepY;             /* the width of each region in y-axis*/
  int offsetX, offsetY;    /* offset from left-top screen corner */
  int i;
  offsetX = 7; offsetY = 2;

  /* find max and min from data */
  minY = maxY = data[0];
  for (i=0; i<regX; i++){
    if (data[i]>maxY) maxY = data[i];
    if (data[i]<minY) minY = data[i];
  }

  stepY = (float)(maxY-minY)/regY;

  /* draw y axis */
  for (i=0; i<=regY+1; i++){
    gotoxy(offsetX-1, i+offsetY+1);
    cprintf("|");
  }
  /* draw x axis*/
  for (i=0; i<(regX+1)*2; i++) cprintf("-");

  /* write labels */
  gotoxy(offsetX-5,offsetY+1); cprintf("days");
  gotoxy(offsetX-5,offsetY+2); cprintf("late");
  gotoxy(offsetX+(regX+1)*2-13,regY+3+offsetY); cprintf("articles read");

  /* plot dots */
  for (i=0; i<regX; i++){
    y = regY+1 - ((int)((float)(data[i]-minY)/stepY)) + offsetY;
    x = (i*2)+offsetX+1;
    gotoxy(x,y); cprintf("*");
  }
}

void AnalyseAdvanced(struct TMARecord records[], int size){
  int artRead[regX];       /* seperate articlesRead to different rooms*/
  float steps, stepX;      /* width of each x-region */
  int i, j = 0;

  /* sort data according to articlesRead */
  sortStruct(records, sizeof(TMARecord), size);

  /* initialize */
  steps = stepX = (float)(records[size-1].articlesRead-records[0].articlesRead)/regX;
  for (i=0; i<regX; i++) artRead[i] = 0;

  printf("Relationship between article reading pattern & TMA late submission\n");

  /* store sorted data into regions */
  for (i=1; i<=size; i++){
    if (records[i].articlesRead>steps){j++; steps += stepX;}
    artRead[j] += records[i-1].daysLate;
  }

  /* display figures */
  printf("\n\t\tRead articles\t     Days late\n");
  printf("\t\t %3d-%3d\t\t%3d\n", 0, (int)(stepX), artRead[0]);
  for (i=1; i<regX-1; i++)
    printf("\t\t %3d-%3d\t\t%3d\n", (int)(stepX*(i))+1, (int)(stepX*(i+1)), artRead[i]);
  printf("\t\t %3d or more\t\t%3d\n",(int)(stepX*(i))+1, artRead[i]);

  /* move cursor to last line */
  gotoxy(1,25); cprintf("Press Enter for next page...");

  /* next page, plot graph */
  getchar(); clrscr();
  printf("Relationship between article reading pattern & TMA late submission\n");
  plot(artRead);
  gotoxy(1,23); cprintf("Press Enter to finish...");
}

/* Prints all the records currently stored in the array records */
void printRecords() {
    for (int i=0; i<recordCount; i++)   {
        printf("%s %d %d %d %d\n",
            records[i].studentid,
            records[i].group,
            records[i].daysLate,
            records[i].articlesRead,
            records[i].articlesPosted);
    }
}

/* Loads records from a file and stores in the array records */
void loadRecordFile(char* f) {
    FILE* infile;
    char buffer[256];
    /* open the file first and report errors if necessary */
    if ((infile = fopen(f, "r")) == NULL)    {
        fprintf(stderr, "Error in loading '%s'.\n", f);
        getchar();
        exit(1);
    }
    /* read the file line by line and add every record to the array */
    while (fgets(buffer, 256, infile) != NULL)    {
        if (sscanf(buffer, "%s %d %d %d %d",
            records[recordCount].studentid,
            &(records[recordCount].group),
            &(records[recordCount].daysLate),
            &(records[recordCount].articlesRead),
            &(records[recordCount].articlesPosted)) != 5)   {
        fprintf(stderr, "Error in reading file at record line %d.\n", recordCount);
        getchar();
        exit(1);
        }
        recordCount++;
    }
    fclose(infile);
}

/* main driving program */
int main()
{
    loadRecordFile("q3ddata.txt");
    /* printRecords();  */
    LateAndEarlyGroups(records, recordCount);
    AnalyseDiscussion(records, recordCount);
    AnalyseAdvanced(records, recordCount);
    getchar();
    return 0;
}




back