/*----------------------------------------------------------------------*/
/* Richard Roy                                                          
   The Interactive Exam Version 1.4  3/14/95   
   
   Copyright Richard Roy        
   Modified by Erich Schneider (erich@bush.cs.tamu.edu)

   This program reads a formatted input file and input from stdin
 to correct an exam and send the results 
 in HTML format to stdout.  Should be called tie/input-file.  
 Input-file should be an absolute pathname.  Normally called by
 an exam generated automatically by tiegen.

*/
/*----------------------------------------------------------------------*/  

#define MAX_QUESTIONS 200
#define MAX_ANSWERS 10
#define MAX_LINE 8000


/* End user configurable items */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "cgiutils.h"

int mycmp(char *input,char *pattern)
{
  int i,length,plength;

  length=strlen(input);
  plength=strlen(pattern);

  for (i=0;i<length;i++) {
    if (i<plength) {
      if (pattern[i]!=input[i]) return(0);
    }
    else {
      if (input[i]!='\n' && input[i]!='\t' && input[i]!=' ') return(0);
    }
  }

  return (1);

}

int isnum(char *input,int length)
{
  int i;

  for (i=0;i<length;i++) if (!isdigit(input[i])) return(0);
  return(1);
}

int main()
{
  int i,j,k,quest,length,feedback[MAX_QUESTIONS],count,index,result,max;
  int state,ans,new,right,wrong,done;
  int question_num=1,answer_num=1,short_ans=0;
  char *string_table[MAX_QUESTIONS];
  char ch,num_string[MAX_LINE],input_str[MAX_LINE],check_str[MAX_LINE];
  char question[MAX_LINE],answer[MAX_ANSWERS][MAX_LINE];
  char *content,*buffer,cans[5],include_top[MAX_LINE],include_middle[MAX_LINE];
  char include_bottom[MAX_LINE],footer[MAX_LINE],*filename;
  FILE *infile;
  float percent,total;
  char wrong_str[1024] ;

  for (i=0;i<MAX_QUESTIONS;i++) {
    string_table[i]=NULL;	/* Initialize table for pointer array approach */
    feedback[i]=0;
  }

  filename = getenv("PATH_INFO"); 

  content = getenv("CONTENT_LENGTH");
  length = atoi(content);

  sprintf(wrong_str, "_") ;

  return_header("text/html") ;

  if ((infile = fopen(filename,"r"))==NULL) {
    printf("<hr><img src=/FLORA/tie_icons/caution.gif>");
    printf("<h1>Cannot open input file: ");
    if (filename != NULL) printf("%s",filename);
    printf("<p>Please contact server administration. ");
    printf("<hr>");	         
    return(0);
  }


  /* at this point we have good inputs, and can start parsing the return from the server */

  count=0;max=0;ans=0;

  for (i=0;i<length;i++) {
    ch=getc(stdin);
    
    if (ch=='=') {
      num_string[count]='\0'; index= atoi(num_string); count=0;
      if (index>max) max = index;
    }
    else if (ch=='&') {
      num_string[count]='\0'; if (count!=0) {
	if (isnum(num_string,count)) {
	  result= atoi(num_string); count=0; feedback[index]=result;
	  ans++;
	}
                                   
	else {
	  string_table[index]= calloc(count,sizeof(char));
	  if (!string_table[index]) {
	    printf("allocation failure!!");exit(1);
	  }
	  strcpy (string_table[index],num_string);
	  feedback[index]=1; 
	  ans++;
	  count=0;
	}
      }
    }                                
    /* save as an array and point to it and make feedback true so gets corrected!!  */

    else {
      if (ch=='+') ch=' '; num_string[count]=ch; count++;
    }
 
  }

 
  num_string[count]='\0';
  if (count!=0) {
    if (isnum(num_string,count)) {
      result= atoi(num_string); count=0; feedback[index]=result;
      ans++;
    }
                                   
    else {
      string_table[index]= calloc(count,sizeof(char));
      if (!string_table[index]) {
	printf("allocation failure!!");exit(1);
      }
      strcpy (string_table[index],num_string);
      feedback[index]=1; 
      ans++;
      count=0;
    }
  }  



  if (ans==0) {
    printf("<hr><img src=/FLORA/tie_icons/caution.gif>");
    printf("<h1>Your Comments appear to be blank.<p>  Please Try Again.</h1><hr>");
    return(0);
  }


  /* at this point we have built a hashing table based upon the answers */
  /* now it is time to read the right answers from infile and compare.  */ 
  /* infile is expected to be in the proper format.  However unlike the */
  /* output from the server this cannot be assumed to be error free.    */

  /* string initializations */

  quest=0;new=0;question[0]='\0';cans[0]='\0';
  include_top[0]='\0';include_middle[0]='\0';include_bottom[0]='\0';
  for (i=0;i<MAX_ANSWERS;i++) answer[i][0]='\0'; 
  right=0;wrong=0;short_ans=0;done=0;

  /* end string initializations */

  printf("<title>Results</title>");
  /* printf("<img src=/FLORA/tie_icons/caution.gif>");  */
  printf("<h1>Your interactive exam results:</h1>");
  printf("<hr> ");
  printf("<h4>Your answer appears in bold.  An incorrect response is marked with a red mark.");
  printf("  Correct responses have a green checkmark. Only questions that have been answered are scored.");
  printf("  For short answer questions your answer is displayed along with a sample answer provided by ");
  printf("your instructor.  However, short answer questions cannot be scored.</h4><hr>");

  for (;;) {
    if (feof(infile))  {
      quest++;buffer=question;input_str[0]='\0';new=1;done=1;length=18;
    }
    else {
      fgets(input_str,MAX_LINE,infile);
      if (input_str[strlen(input_str)-2] == (char)13) {
	input_str[strlen(input_str)-2] = '\n' ;
	input_str[strlen(input_str)-1] = '\0' ;
      }
      length=strlen(input_str);
    }

    if (length<18) {
      strcpy(check_str,input_str);
      for (j=0;j<length;j++) check_str[j]=toupper(check_str[j]);
      if (mycmp(check_str,"QUESTION:")) {
	quest++;buffer=question;input_str[0]='\0';new=1;
      }
      if (mycmp(check_str,"ANS:")) {
	buffer=answer[ans];ans++;input_str[0]='\0';
      }
      if (mycmp(check_str,"CORRECT_ANSWER:")) {
	buffer=cans;input_str[0]='\0';
      }
      if (mycmp(check_str,"INCLUDE_TOP:")) {
	buffer=include_top;input_str[0]='\0';
      }
      if (mycmp(check_str,"INCLUDE_BOTTOM:")) {
	buffer=include_bottom;input_str[0]='\0';
      }
      if (mycmp(check_str,"INCLUDE_MIDDLE:")) {
	buffer=include_middle;input_str[0]='\0';
      }
      if (mycmp(check_str,"TITLE:")) {
	buffer=include_top;input_str[0]='\0';
      }
      if (mycmp(check_str,"HEADER:")) {
	buffer=include_top;input_str[0]='\0';
      } 
      if (mycmp(check_str,"FOOTER:")) {
	buffer=footer;input_str[0]='\0';
      }
      if (mycmp(check_str,"QUESTION_NUM:")) {
	!(question_num);input_str[0]='\0'; 
      }
      if (mycmp(check_str,"ANSWER_NUM:")) {
	!(answer_num);input_str[0]='\0';
      } 
      if (mycmp(check_str,"SHORT_ANS:")) {
	short_ans=1;input_str[0]='\0'; 
      }
    }

    strcat(buffer,input_str); 

   

    if (feedback[quest-1] && new && quest>1) {
      if (short_ans) {
        printf("%s",include_top);
	if (question_num) printf("%i)",quest-1);
	printf("  %s<br>\n",question);
	printf("%s",include_middle);
	if (string_table[quest-1]) printf("<ul><dt><b>You answered:</b><dt>%s<p>",string_table[quest-1]);
	else printf("<ul><dt><b>You answered:</b><dt>%i<p>",feedback[quest-1]);
	printf("<dt><b>Your instructor answered:</b><dt>%s</ul>",cans);
	short_ans=0;
      }

      else {
	int correct_answer = 0 ;

	if (atoi(cans)==feedback[quest-1]) {
          right++;
	  correct_answer = 1 ;
	}
	else {
	  char temp_str[1024] ;
	  wrong++ ;
	  sprintf(temp_str, "%s%d_", wrong_str, quest-1) ;
	  strcpy(wrong_str, temp_str) ;
	}

	printf("%s",include_top);
	if (question_num) printf("%i)",quest-1);
	printf("  %s<p>\n",question);
	printf("%s",include_middle);
	printf("<ol>\n");

	for (j=0;j<ans;j++) {
	  printf("<li>") ;
	  if (j+1==feedback[quest-1]) {
	    if (correct_answer)
	      printf("<img src=\"/FLORA/tie_icons/check.gif\">") ;
	    else 
	      printf("<img src=\"/FLORA/tie_icons/x.gif\">") ;
	    printf("<b>%s</b>", answer[j]) ;
	  }
	  else
	    printf("%s", answer[j]) ;
	}
	printf("</ol>");
	printf("%s",include_bottom);  
      }
      
      question[0]='\0';cans[0]='\0';
      include_top[0]='\0';include_middle[0]='\0';include_bottom[0]='\0';
      for (i=0;i<MAX_ANSWERS;i++) answer[i][0]='\0';
      new=0;ans=0;short_ans=0; 
    }
    
    if (new) {
      question[0]='\0';cans[0]='\0';
      include_top[0]='\0';include_middle[0]='\0';include_bottom[0]='\0';
      for (i=0;i<MAX_ANSWERS;i++) answer[i][0]='\0';
      new=0;ans=0;short_ans=0;
    }

    if (done) break;
  }

  printf("%s",footer);

  total=right+wrong;
  printf("<hr>");
  if (total) {
    printf("<h3>You scored %d right and %d wrong for a score of %5.2f%%</h3>",
	   right,wrong,(right/total)*100.0);
    if (wrong > 0) {
      printf("If you wish, you may ") ;
      if (filename[0] == '/')
	printf("<a href=\"/FLORA/cgi/tiegen/%s?%s\">", filename+1, wrong_str) ;
      else
	printf("<a href=\"/FLORA/cgi/tiegen/%s?%s\">", filename, wrong_str) ;
	
      printf("retry the questions you missed") ;
      printf("</a>") ;
      printf(".") ;
    }
  }
}
