File:  [LON-CAPA] / capa / capa51 / GUITools / quizzer.funct.c
Revision 1.3: download - view: text, annotated - select for diffs
Fri Aug 4 15:54:49 2000 UTC (23 years, 9 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- modified build method to be less error prone
- corrected some english in the INSTALL file

    1: /* c interfaces for Quizzer
    2:    Copyright (C) 1992-2000 Michigan State University
    3: 
    4:    The CAPA system is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Library General Public License as
    6:    published by the Free Software Foundation; either version 2 of the
    7:    License, or (at your option) any later version.
    8: 
    9:    The CAPA system is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    Library General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Library General Public
   15:    License along with the CAPA system; see the file COPYING.  If not,
   16:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   17:    Boston, MA 02111-1307, USA.
   18: 
   19:    As a special exception, you have permission to link this program
   20:    with the TtH/TtM library and distribute executables, as long as you
   21:    follow the requirements of the GNU GPL in regard to all of the
   22:    software in the executable aside from TtH/TtM.
   23: */
   24: 
   25: /*
   26:  * quizzer.funct.c
   27:  * Guy Albertelli II 1996
   28:  */
   29: #include <stdio.h>
   30: #include <tk.h>
   31: #include <pProj/capaCommon.h>
   32: #include <quizzer.h>
   33: #include <common.h>
   34: #include <ctype.h>
   35: #include <time.h>
   36: #include <signal.h>
   37: #include <sys/types.h>
   38: #include <sys/wait.h>
   39: #include <errno.h>
   40: 
   41: extern  int errno;
   42: extern  int Parsemode_f;
   43: static  int capaParsing;
   44: static  int gCreateDvi;
   45: void capaQuizzerStatus();
   46: 
   47: T_header gCapaHeader;
   48: static char* gPreviewText;
   49: int capaTclParse (ClientData clientdata, Tcl_Interp *interp, int argc, 
   50: 		  char *argv[])
   51: {
   52: 
   53:   extern  char      *EndText_p;
   54:   extern  char      *StartText_p;
   55:   T_student student;
   56:   Problem_t *headProblem,*currentProblem;
   57:   int numOfQuestions,numAnswers,problemNumber=0;
   58:   int result,i=1,j,length;
   59:   char *buf, *buf2, *temp, *previewText=NULL;
   60:   char lower[32],upper[32],ans[64], unit[64];
   61:   double  targetAns;
   62: #ifdef QUIZZER_UPDATE
   63:   char *update=";update";
   64: #else
   65:   char *update=" ";
   66: #endif
   67: 
   68:   capaParsing = 1;
   69:   switch(argv[0][0])
   70:     {
   71:     case 'e':Parsemode_f = ASCII_MODE;break;
   72:     case 't':Parsemode_f = TeX_MODE;break;
   73:     case 'w':Parsemode_f = HTML_MODE;break;
   74:     default:
   75:       Tcl_ResetResult(interp);
   76:       Tcl_AppendElement(interp,"Invalid call to capaTclParse\n");
   77:       capaParsing=0;
   78:       return TCL_ERROR;
   79:       break;
   80:     }
   81: 
   82:   if (argc==9) { gCreateDvi=atoi(argv[8]); } else { gCreateDvi=0; }
   83: 
   84:   if ( (previewText = Tcl_GetVar(interp,argv[7],
   85: 				 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)
   86:     {
   87:       fprintf(stderr,"Tcl_GetVar error\n");
   88:       fprintf(stderr,"%s\n",interp->result);
   89:       capaParsing=0;
   90:       return TCL_ERROR;
   91:     }
   92:   gPreviewText=previewText;
   93:   switch (argv[3][0])
   94:     {
   95:     case 'R':
   96:       result = capa_pick_student(atoi(argv[4]),&student);
   97:       if (result == -1)
   98: 	{
   99: 	  buf=capa_malloc(BUFFER_SIZE,1);
  100: 	  sprintf(buf,"displayError \"There are no students in section %d.\"",
  101: 		  atoi(argv[4]));
  102: 	  Tcl_Eval(interp,buf);
  103: 	  capa_mfree(buf);
  104: 	  Tcl_ResetResult(interp);
  105: 	  Tcl_AppendElement(interp,"-1");
  106: 	  capaParsing = 0;
  107: 	  return TCL_ERROR;
  108: 	}
  109:       result = capa_parse(atoi(argv[2]),&headProblem,student.s_sn,
  110: 			  &numOfQuestions,capaQuizzerStatus);
  111:       break;
  112:     case 'S':
  113:       result = capa_get_student(argv[5],&student);
  114:       if ((result == -1) || (result == 0))
  115: 	{
  116: 	  buf=capa_malloc(BUFFER_SIZE,1);
  117: 	  sprintf(buf,"displayError \"The student %s does not exist.\"",
  118: 		  argv[5]);
  119: 	  Tcl_Eval(interp,buf);
  120: 	  capa_mfree(buf);
  121: 	  Tcl_ResetResult(interp);
  122: 	  Tcl_AppendElement(interp,"-1");
  123: 	  capaParsing = 0;
  124: 	  return TCL_ERROR;
  125: 	}
  126:       result = capa_parse(atoi(argv[2]),&headProblem,argv[5],&numOfQuestions,
  127: 			  capaQuizzerStatus);
  128:       break;
  129:     default:
  130:       Tcl_ResetResult(interp);
  131:       Tcl_AppendElement(interp,"Invalid 2nd argument to capaTclParse\n");
  132:       capaParsing = 0;
  133:       return TCL_ERROR;
  134:       break;
  135:     }
  136: 
  137:   if (result==-1)
  138:     {
  139:       Tcl_ResetResult(interp);
  140:       Tcl_AppendElement(interp,"-1");
  141:       capaParsing = 0;
  142:       return TCL_OK;
  143:     }
  144: 
  145:   currentProblem=headProblem;
  146:   buf=capa_malloc(BUFFER_SIZE,1);
  147:   sprintf(buf,"%s del 0.0 end %s",previewText,update);
  148:   if (Tcl_Eval(interp,buf) != TCL_OK)
  149:     {
  150:       fprintf(stderr,"Tcl_Eval error 2a\n");
  151:       fprintf(stderr,"%s\n",interp->result);
  152:       capaParsing = 0;
  153:       return TCL_ERROR;
  154:     }
  155:   capa_mfree(buf);
  156: 
  157:   /* if in answer only mode or ascii mode put a useful header on top */
  158:   if(argv[1][0] == Q_ANSWER || Parsemode_f == ASCII_MODE )
  159:     { 
  160:       buf=capa_malloc(BUFFER_SIZE,1);
  161:       buf2=capa_malloc(BUFFER_SIZE,1);
  162:       switch(Parsemode_f)
  163: 	{
  164: 	case ASCII_MODE:
  165: 	  sprintf(buf,"Section %d                               Set %d\n Name: %s CAPAID: %d\n\n",
  166: 		  student.s_sec, atoi(argv[2]), student.s_nm,
  167: 		  capa_PIN(student.s_sn, atoi(argv[2]),0));
  168: 	  break;
  169: 	case TeX_MODE:
  170: 	  
  171: 	  sprintf(buf,"Section %d  {\\Large %s}\\hspace*{1in}{\\large %s}, CAPAID: %d, set%d\n\\begin{enumerate}", 
  172: 		  student.s_sec, student.s_nm, student.s_sn,
  173: 		  capa_PIN(student.s_sn, atoi(argv[2]),0), atoi(argv[2]));
  174: 	  break;
  175: 	case HTML_MODE:
  176: 	  sprintf(buf,"<H2>Section %d  %s,  %s, CAPAID:%d set %d</H2>\n<OL>\n", 
  177: 		  student.s_sec, student.s_nm, student.s_sn,
  178: 		  capa_PIN(student.s_sn, atoi(argv[2]),0), atoi(argv[2]));
  179: 	  break;
  180: 	}
  181:       j=capaPrepareBuffer(buf,buf2,0);
  182:       
  183:       sprintf(buf,"%s insert end \" %s \" header%s",previewText,buf2,update);
  184:       
  185:       if (Tcl_Eval(interp,buf) != TCL_OK)
  186: 	{
  187: 	  fprintf(stderr,"Tcl_Eval error 2\n");
  188: 	  fprintf(stderr,"%s\n",interp->result);
  189: 	  capaParsing = 0;
  190: 	  return TCL_ERROR;
  191: 	}
  192:       capa_mfree(buf);
  193:       capa_mfree(buf2);
  194:     }
  195: 
  196:   if ( gCapaHeader.weight != NULL ) { capa_mfree(gCapaHeader.weight); } 
  197:   if ( gCapaHeader.partial_credit != NULL ) { capa_mfree(gCapaHeader.partial_credit); } 
  198:   gCapaHeader.weight= capa_malloc(numOfQuestions+1,1);
  199:   gCapaHeader.partial_credit= capa_malloc(numOfQuestions+1,1);
  200: 
  201:   if( ( StartText_p != NULL) ) 
  202:     {
  203:       buf=capa_malloc(BUFFER_SIZE+(2*strlen(StartText_p)),1);
  204:       buf2=capa_malloc(BUFFER_SIZE+(2*strlen(StartText_p)),1);
  205:       temp=capa_malloc(BUFFER_SIZE+(2*strlen(StartText_p)),1);
  206:       sprintf(temp,"%s", StartText_p);
  207:       j=capaPrepareBuffer(temp,buf2,0);
  208:       
  209:       sprintf(buf,"%s insert end \"%s\" answer%s",previewText,buf2,update);
  210:       
  211:       if (Tcl_Eval(interp,buf) != TCL_OK)
  212:         {
  213: 	  fprintf(stderr,"Tcl_Eval error 8\n");
  214: 	  fprintf(stderr,"%s\n",interp->result);
  215: 	  capaParsing = 0;
  216: 	  return TCL_ERROR;
  217: 	}
  218:       capa_mfree(buf);
  219:       capa_mfree(buf2);
  220:       capa_mfree(temp);
  221:     }
  222:   
  223:   while (currentProblem!=NULL)
  224:     {
  225:       gCapaHeader.weight[problemNumber]=((char)(currentProblem->weight))+'0';
  226:       gCapaHeader.partial_credit[problemNumber]=
  227: 	((char)(currentProblem->partial_cdt))+'0';
  228:       switch (argv[1][0])
  229: 	{
  230: 	case Q_PROBLEM:
  231: 	  if (currentProblem->question) { 
  232: 	    length=strlen(currentProblem->question); 
  233: 	  } else { 
  234: 	    length=0;
  235: 	  }
  236: 	  buf=capa_malloc(BUFFER_SIZE+(2*length),1);
  237: 	  buf2=capa_malloc(BUFFER_SIZE+(2*length),1);
  238: 	  if(currentProblem->question) {
  239: 	    j=capaPrepareBuffer(currentProblem->question,buf2,0);
  240: 	    buf2[j-1]='\n';
  241: 	    buf2[j]='\0';
  242: 	  } else {
  243: 	    buf2[0]='\n';buf2[1]='\0';
  244: 	  }
  245: 	  
  246: 	  switch(Parsemode_f)
  247: 	    {
  248: 	    case ASCII_MODE:
  249: 	      sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem%s",
  250: 		      previewText,buf2,update);
  251: 	      break;
  252: 	    case TeX_MODE:
  253: 	      sprintf(buf,"%s insert end \"%s\" problem%s",previewText,buf2,update);
  254: 	      break;
  255: 	    case HTML_MODE:
  256: 	      sprintf(buf,"%s insert end \"%s\" problem%s",previewText,buf2,update);
  257: 	      break;
  258: 	    }	  
  259: 	  if (Tcl_Eval(interp,buf) != TCL_OK)
  260: 	    {
  261: 	      fprintf(stderr,"Tcl_Eval error 3\n");
  262: 	      fprintf(stderr,"%s\n",interp->result);
  263: 	      capaParsing = 0;
  264: 	      return TCL_ERROR;
  265: 	    }
  266: 	  capa_mfree(buf);
  267: 	  capa_mfree(buf2);
  268: 	  break;
  269: 	case Q_PROBLEM_AND_ANSWER:
  270: 	  if (currentProblem->question) { 
  271: 	    length=strlen(currentProblem->question); 
  272: 	  } else { 
  273: 	    length=0;
  274: 	  }
  275: 	  buf=capa_malloc(BUFFER_SIZE+(2*length),1);
  276: 	  buf2=capa_malloc(BUFFER_SIZE+(2*length),1);
  277: 	  temp=capa_malloc(BUFFER_SIZE+(2*length),1);
  278: 	  if (currentProblem->question) 
  279: 	    j=capaPrepareBuffer(currentProblem->question,buf2,0);
  280: 	  switch(Parsemode_f)
  281: 	    {
  282: 	    case ASCII_MODE:
  283: 	      sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem%s",
  284: 		      previewText,buf2,update);
  285: 	      break;
  286: 	    case TeX_MODE:
  287: 	      sprintf(buf,"%s insert end \"%s\" problem%s",previewText,buf2,update);
  288: 	      break;
  289: 	    case HTML_MODE:
  290: 	      sprintf(buf,"%s insert end \"%s\" problem%s",previewText,buf2,update);
  291: 	      break;
  292: 	    } 
  293: 	  if (Tcl_Eval(interp,buf) != TCL_OK)
  294: 	    {
  295: 	      fprintf(stderr,"Tcl_Eval error 4\n");
  296: 	      fprintf(stderr,"%s\n",interp->result);
  297: 	      capaParsing = 0;
  298: 	      return TCL_ERROR;
  299: 	    }	  
  300: 	  capa_mfree(buf);
  301: 	  capa_mfree(buf2);
  302: 	  capa_mfree(temp);
  303: 	  capaInsertAnswer(currentProblem,interp,previewText);
  304: 	  break;
  305: 	case Q_ANSWER:
  306: 	  print_begin_item(Parsemode_f,interp,previewText,problemNumber+1);
  307: 	  capaInsertAnswer(currentProblem,interp,previewText);
  308: 	  break;
  309: 	}
  310: 
  311:       currentProblem=currentProblem->next;
  312:       problemNumber++;
  313:     }
  314: 
  315:   if(argv[1][0] == Q_ANSWER && Parsemode_f == TeX_MODE )  { 
  316:     buf=capa_malloc(BUFFER_SIZE,1);
  317:     buf2=capa_malloc(BUFFER_SIZE,1);
  318:     sprintf(buf,"\n\\end{enumerate}\n");
  319:     j=capaPrepareBuffer(buf,buf2,0);
  320:     
  321:     sprintf(buf,"%s insert end \" %s \" header%s",previewText,buf2,update);
  322:     
  323:     if (Tcl_Eval(interp,buf) != TCL_OK)	{
  324:       fprintf(stderr,"Tcl_Eval error 2\n");
  325:       fprintf(stderr,"%s\n",interp->result);
  326:       capaParsing = 0;
  327:       return TCL_ERROR;
  328:     }
  329:     capa_mfree(buf);
  330:     capa_mfree(buf2);
  331:   }
  332: 
  333:   if( ( EndText_p != NULL) ) 
  334:     {
  335:       buf=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  336:       buf2=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  337:       temp=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  338:       sprintf(temp,"%s", EndText_p);
  339:       j=capaPrepareBuffer(temp,buf2,0);
  340:       
  341:       sprintf(buf,"%s insert end \"%s\" answer%s",previewText,buf2,update);
  342:       
  343:       if (Tcl_Eval(interp,buf) != TCL_OK)
  344:         {
  345: 	  fprintf(stderr,"Tcl_Eval error 7\n");
  346: 	  fprintf(stderr,"%s\n",interp->result);
  347: 	  capaParsing = 0;
  348: 	  return TCL_ERROR;
  349: 	}
  350:       capa_mfree(buf);
  351:       capa_mfree(buf2);
  352:       capa_mfree(temp);
  353:     }
  354:   free_problems(headProblem);
  355:   free_units();
  356:   gCapaHeader.weight[problemNumber]='\0';
  357:   gCapaHeader.partial_credit[problemNumber]='\0';
  358: 
  359:   if (result==0) 
  360:     {
  361:       Tcl_ResetResult(interp);
  362:       Tcl_AppendElement(interp,"0");
  363:     }
  364:   else
  365:     {
  366:       buf=capa_malloc(BUFFER_SIZE,1);
  367:       sprintf(buf,"%d",result);
  368:       Tcl_ResetResult(interp);
  369:       Tcl_AppendElement(interp,buf);
  370:       capa_mfree(buf);
  371:     }
  372:   capaParsing = 0;
  373:   return TCL_OK;
  374: }
  375: 
  376: int capaGetStudent(ClientData clientdata, Tcl_Interp *interp, int argc, 
  377: 		   char *argv[])
  378: {
  379:   T_student student;
  380:   int result;
  381:   char buf[BUFFER_SIZE];
  382: 
  383:   result = capa_get_student(argv[1],&student);
  384: 
  385:   Tcl_ResetResult(interp);
  386: 
  387:   switch (result)
  388:     {
  389:     case -1:
  390:       Tcl_AppendElement(interp,"File path incorrect");
  391:       break;
  392:     case 0:
  393:       Tcl_AppendElement(interp,"No such student");
  394:       break;
  395:     default:
  396:       Tcl_ResetResult(interp);
  397:       sprintf(buf,"%d",student.s_sec);
  398:       Tcl_AppendElement(interp,buf);
  399:       sprintf(buf,"%d",student.s_scores);
  400:       Tcl_AppendElement(interp,buf);
  401:       Tcl_AppendElement(interp,student.s_key);
  402:       Tcl_AppendElement(interp,student.s_sn);
  403:       Tcl_AppendElement(interp,student.s_nm);
  404:       break;
  405:     }
  406:   return TCL_OK;
  407: }
  408: 
  409: int capaRunLatex(ClientData clientdata, Tcl_Interp *interp, int argc, 
  410: 		 char *argv[])
  411: {
  412:   FILE* output;
  413:   char *textWindow,buf[BUFFER_SIZE],buf2[BUFFER_SIZE*2],
  414:     command[BUFFER_SIZE*3],*stopPrinting;
  415:   char *compString="Output written on quiztemp.dvi";
  416:   int createdDvi=0,stop=0,i,update=0;
  417: 
  418:   if ( (output = popen(argv[1],"r"))==NULL) {
  419:     fprintf(stderr,"popen failed");
  420:   }
  421: 
  422:   if ( (textWindow = Tcl_GetVar(interp,argv[2],
  423: 				TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)  {
  424:     fprintf(stderr,"Tcl_GetVar error\n");
  425:     fprintf(stderr,"%s\n",interp->result);
  426:     return TCL_ERROR;
  427:   }  
  428: 
  429:   while(fgets(buf,BUFFER_SIZE-1,output)) {
  430:     if (strncmp(compString,buf,strlen(compString))==0)  createdDvi=1;
  431:     
  432:     capaPrepareBuffer(buf,buf2,0);
  433:     
  434:     sprintf(command,"%s insert end \"%s\" answer",textWindow, buf2);
  435:     
  436:     if (Tcl_Eval(interp,command) != TCL_OK) {
  437:       fprintf(stderr,"Tcl_Eval error\n");
  438:       fprintf(stderr,"%s\n",interp->result);
  439:       return TCL_ERROR;
  440:     }
  441:     
  442:     if (Tcl_Eval(interp,"update") != TCL_OK) {
  443:       fprintf(stderr,"Tcl_Eval error\n");
  444:       fprintf(stderr,"%s\n",interp->result);
  445:       return TCL_ERROR;
  446:     }
  447:      
  448:     if (update++ > 10) {
  449:       sprintf(command,"%s see end",textWindow, buf2);
  450:       
  451:       if (Tcl_Eval(interp,command) != TCL_OK) {
  452: 	fprintf(stderr,"Tcl_Eval error\n");
  453: 	fprintf(stderr,"%s\n",interp->result);
  454: 	return TCL_ERROR;
  455:       }
  456:       update=0;
  457:     }
  458:     if ( (stopPrinting = Tcl_GetVar(interp,"gStopPrinting",
  459: 				    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL) {
  460:       fprintf(stderr,"Tcl_GetVar error\n");
  461:       fprintf(stderr,"%s\n",interp->result);
  462:       return TCL_ERROR;
  463:     }
  464:     stop=atoi(stopPrinting);
  465:     if (stop) {
  466:       for(i=1;i< 32768;i++) {
  467: 	waitpid(i,NULL,WNOHANG);
  468: 	if (errno!=ECHILD) { errno=0;break; }
  469: 	errno=0;
  470:       }
  471:       if ( i < 32768 ) { kill(i,SIGKILL); }
  472:       break;
  473:     }
  474:   }
  475:   
  476:   sprintf(command,"%s see end",textWindow, buf2);
  477:   
  478:   if (Tcl_Eval(interp,command) != TCL_OK) {
  479:     fprintf(stderr,"Tcl_Eval error\n");
  480:     fprintf(stderr,"%s\n",interp->result);
  481:     return TCL_ERROR;
  482:   }  
  483:   pclose(output);
  484:   
  485:   if (stop) {
  486:     Tcl_ResetResult(interp);
  487:     Tcl_AppendElement(interp,"2");
  488:     return TCL_OK;
  489:   } 
  490:   if (createdDvi) {
  491:     Tcl_ResetResult(interp);
  492:     Tcl_AppendElement(interp,"1");
  493:   } else {
  494:     Tcl_ResetResult(interp);
  495:     Tcl_AppendElement(interp,"0");
  496:   }
  497:   return TCL_OK;
  498: }
  499: 
  500: int capaGetParseErrors(ClientData clientdata, Tcl_Interp *interp, 
  501: 		       int argc, char *argv[])
  502: {
  503:   extern int ErrorMsg_count;
  504:   extern char *ErrorMsg_p;
  505: 
  506:   if (ErrorMsg_count > 0)
  507:     {
  508:       Tcl_ResetResult(interp);
  509:       Tcl_SetResult(interp,ErrorMsg_p,TCL_VOLATILE);
  510:     }
  511:   else
  512:     {
  513:       Tcl_ResetResult(interp);
  514:     }
  515:   return TCL_OK;  
  516: }
  517: 
  518: int capaGetHeaderInfo(ClientData clientdata, Tcl_Interp *interp, 
  519: 		      int argc, char *argv[])
  520: {
  521:   T_header header;
  522:   T_dates  *dates,*current;
  523:   char * setNumber,buf[BUFFER_SIZE],*buf2;
  524:   int set,result,i;
  525: 
  526:   setNumber=Tcl_GetVar(interp,"gLoadHeaderSet",TCL_GLOBAL_ONLY);
  527: 
  528:   if ( setNumber== NULL || setNumber[0] == '\0') {
  529:     Tcl_ResetResult(interp);
  530:     Tcl_AppendElement(interp,"called getHeaderInfo with no gLoadHeaderSet value");    
  531:     return TCL_ERROR;
  532:   }
  533: 
  534:   sscanf(setNumber,"%d",&set);
  535: 
  536:   result=capa_get_header(&header,set);
  537:   
  538:   if (result == -1 ) {
  539:     Tcl_ResetResult(interp);
  540:     Tcl_AppendElement(interp,"capa_get_header return a -1");    
  541:     return TCL_ERROR;
  542:   }
  543: 
  544:   Tcl_SetVar(interp,"gWeightsDiffer","0",TCL_GLOBAL_ONLY);
  545:   if (gCapaHeader.weight!=NULL && header.weight !=NULL) {
  546:     for(i=0;i<(strlen(header.weight)&&strlen(gCapaHeader.weight));i++) {
  547:       if (header.weight[i]!=gCapaHeader.weight[i]) {
  548: 	Tcl_SetVar(interp,"gWeightsDiffer","1",TCL_GLOBAL_ONLY);break;
  549:       }
  550:     }
  551:   }
  552:   capa_mfree(header.weight);
  553: 
  554:   if (gCapaHeader.partial_credit!=NULL && header.partial_credit !=NULL) {
  555:     Tcl_SetVar(interp,"gPartialDiffer","0",TCL_GLOBAL_ONLY);
  556:     for(i=0;i<(strlen(header.partial_credit)&&strlen(gCapaHeader.partial_credit));i++) {
  557:       if (header.partial_credit[i]!=gCapaHeader.partial_credit[i]) {
  558: 	Tcl_SetVar(interp,"gPartialDiffer","1",TCL_GLOBAL_ONLY);break;
  559:       }
  560:     }
  561:   }
  562:   capa_mfree(header.partial_credit);
  563: 
  564:   result=capa_get_all_dates(set,&dates);
  565:   if (result < 0 ) {
  566:     Tcl_ResetResult(interp);
  567:     Tcl_AppendElement(interp,"capa_get_header returned a negative number");    
  568:     return TCL_ERROR;
  569:   }
  570: 
  571:   Tcl_SetVar(interp,"gHeaderQCount",header.num_questions,TCL_GLOBAL_ONLY);  
  572: 
  573:   buf2=capa_malloc(result*QUARTER_K,1);
  574:   buf2[0]='\0';
  575:   current=dates;
  576:   while(current != NULL ) {
  577:     sprintf(buf,"{%d %d {%s} {%s} {%s} {%s} %d %d} ",current->section_start,
  578: 	    current->section_end, current->open_date, current->due_date,
  579: 	    current->answer_date, current->duration, current->inhibit_response,
  580: 	    current->view_problems_after_due);
  581:     strcat(buf2,buf);
  582:     current=current->s_next;
  583:   }
  584:   Tcl_SetVar(interp,"gControlDates",buf2,TCL_GLOBAL_ONLY);
  585:   free_dates(dates);
  586:   capa_mfree(buf2);
  587:   return TCL_OK;
  588: }
  589: 
  590: int capaCheckDateFormat(char *varName,Tcl_Interp *interp)
  591: {
  592:   char *tempPoint;
  593: 
  594:   tempPoint=Tcl_GetVar(interp,varName,TCL_GLOBAL_ONLY);
  595: 
  596:   if (strlen(tempPoint)!=8) goto wrong;
  597: 
  598:   switch(tempPoint[0])
  599:     {
  600:     case '0':
  601:       if (!isdigit(tempPoint[1])) goto wrong;
  602:       break;
  603:     case '1':
  604:       if (!(
  605: 	    (tempPoint[1]=='0') ||
  606: 	    (tempPoint[1]=='1') ||
  607: 	    (tempPoint[1]=='2')
  608: 	    )
  609: 	  ) goto wrong;
  610:       break;
  611:     case '2':
  612:       if (!(
  613:             (tempPoint[1]=='0') ||
  614: 	    (tempPoint[1]=='1') ||
  615: 	    (tempPoint[1]=='2') ||
  616: 	    (tempPoint[1]=='3') ||
  617: 	    (tempPoint[1]=='4')
  618: 	   )
  619:          ) goto wrong;
  620:        break;
  621:     default:
  622:       goto wrong;
  623:       break;
  624:     }
  625:   if (tempPoint[2] != '/') goto wrong;
  626:   switch(tempPoint[3])
  627:     {
  628:     case '0':
  629:     case '1':
  630:     case '2':
  631:        if (!isdigit(tempPoint[4])) goto wrong;
  632:       break;
  633:     case '3':
  634:       if (!(
  635: 	    (tempPoint[4]=='0') ||
  636: 	    (tempPoint[4]=='1') 
  637: 	    )
  638: 	  ) goto wrong;
  639:       break;
  640:     default:
  641:       goto wrong;
  642:       break;
  643:     }
  644:   if (tempPoint[5] != '/') goto wrong;
  645:   if (!isdigit(tempPoint[6])) goto wrong;
  646:   if (!isdigit(tempPoint[7])) goto wrong;
  647:   goto right;
  648: wrong:
  649:   return 0;
  650: right:
  651:   return 1;
  652: }
  653: 
  654: int capaCheckTimeFormat(char *varName,Tcl_Interp *interp)
  655: {
  656:   char *tempPoint;
  657: 
  658:   tempPoint=Tcl_GetVar(interp,varName,TCL_GLOBAL_ONLY);
  659: 
  660:   if (strlen(tempPoint)!=5) goto wrong;
  661: 
  662:   switch(tempPoint[0])
  663:     {
  664:     case '0':
  665:       if (!isdigit(tempPoint[1])) goto wrong;
  666:       break;
  667:     case '1':
  668:       if (!(isdigit(tempPoint[1])))
  669: 	  goto wrong;
  670:       break;
  671:     case '2':
  672:       switch(tempPoint[1])
  673: 	{
  674: 	case '0':
  675: 	case '1':
  676: 	case '2':
  677: 	case '3':
  678: 	case '4':
  679: 	  break;
  680: 	default:
  681: 	  goto wrong;
  682: 	  break;
  683: 	}
  684:       break;
  685:     default:
  686:       goto wrong;
  687:       break;
  688:     }
  689:   if (tempPoint[2] != ':') goto wrong;
  690:   switch (tempPoint[3])
  691:     {
  692:     case '0':
  693:     case '1':
  694:     case '2':
  695:     case '3':
  696:     case '4':
  697:     case '5':
  698:       break;
  699:     default:
  700:       goto wrong;
  701:       break;
  702:     }
  703:   if (!isdigit(tempPoint[4])) goto wrong;
  704:   goto right;
  705: 
  706: wrong:
  707:   return 0;
  708: right:
  709:   return 1;
  710: }
  711: 
  712: int capaCheckHeader(ClientData clientdata, Tcl_Interp *interp, 
  713: 		    int argc, char *argv[])
  714: {
  715:   if (!capaCheckDateFormat("gOpenDate",interp)) 
  716:     {
  717:       Tcl_ResetResult(interp);
  718:       Tcl_AppendElement(interp,"0");
  719:       return TCL_OK;
  720:     }
  721:   if (!capaCheckTimeFormat("gOpenTime",interp)) 
  722:     {
  723:       Tcl_ResetResult(interp);
  724:       Tcl_AppendElement(interp,"0");
  725:       return TCL_OK;
  726:     }
  727:   if (!capaCheckDateFormat("gDueDate",interp)) 
  728:     {
  729:       Tcl_ResetResult(interp);
  730:       Tcl_AppendElement(interp,"0");
  731:       return TCL_OK;
  732:     }
  733:   if (!capaCheckTimeFormat("gDueTime",interp)) 
  734:     {
  735:       Tcl_ResetResult(interp);
  736:       Tcl_AppendElement(interp,"0");
  737:       return TCL_OK;
  738:     }
  739:   if (!capaCheckDateFormat("gAnswerDate",interp)) 
  740:     {
  741:       Tcl_ResetResult(interp);
  742:       Tcl_AppendElement(interp,"0");
  743:       return TCL_OK;
  744:     }
  745:   if (!capaCheckTimeFormat("gAnswerTime",interp)) 
  746:     {
  747:       Tcl_ResetResult(interp);
  748:       Tcl_AppendElement(interp,"0");
  749:       return TCL_OK;
  750:     }
  751:   Tcl_ResetResult(interp);
  752:   Tcl_AppendElement(interp,"1");
  753:   return TCL_OK;
  754: }
  755: 
  756: int capaUpdateHeader(ClientData clientdata, Tcl_Interp *interp, 
  757: 		     int argc, char *argv[])
  758: {
  759:   char *setNumber,*date,*time,*questions;
  760:   int set,result,i;
  761:   T_dates *dates;
  762: 
  763:   setNumber=Tcl_GetVar(interp,"gSetNumberText",TCL_GLOBAL_ONLY);
  764: 
  765:   if ( setNumber[0] == '\0' )  return TCL_OK;
  766: 
  767:   sscanf(setNumber,"%d",&set);
  768:   questions=Tcl_GetVar(interp,"gNumberParsedText",TCL_GLOBAL_ONLY);
  769:   sprintf(gCapaHeader.num_questions,"%s",questions);
  770: 
  771:   /*weight and partialcredit info is from the parse*/
  772: 
  773:   result=capa_set_header(&gCapaHeader,set);
  774: 
  775:   if (result == -1) 
  776:     Tcl_Eval(interp,"displayError \"The records directory does not exist or is unwritable.\"");
  777:   else {
  778:     T_dates* current;
  779:     for(i=0;i<argc/8;i++) {
  780:       if ( i==0 ) {
  781: 	dates=current=(T_dates*)capa_malloc(sizeof(T_dates),1);
  782:       } else {
  783: 	current->s_next=(T_dates*)capa_malloc(sizeof(T_dates),1);
  784: 	current=current->s_next;
  785:       }
  786:       current->section_start=atoi(argv[(i*8)+1]);
  787:       current->section_end=atoi(argv[(i*8)+2]);
  788:       strncpy(current->open_date,argv[(i*8)+3],sizeof(current->open_date));
  789:       strncpy(current->due_date,argv[(i*8)+4],sizeof(current->due_date));
  790:       strncpy(current->answer_date,argv[(i*8)+5],sizeof(current->answer_date));
  791:       strncpy(current->duration,argv[(i*8)+6],sizeof(current->duration));
  792:       current->inhibit_response=atoi(argv[(i*8)+7]);
  793:       current->view_problems_after_due=atoi(argv[(i*8)+8]);
  794:     }
  795:     result=capa_set_all_dates(set,dates);
  796:     free_dates(dates);
  797:     if (result == -1) 
  798:       Tcl_Eval(interp,"displayError \"The records directory does not exist or is unwritable.\"");
  799:   }
  800:   return TCL_OK;
  801: }
  802: 
  803: int capaGetStudentNumbers(ClientData clientdata, Tcl_Interp *interp, 
  804: 			int argc, char *argv[])
  805: {
  806:   char buf[BUFFER_SIZE];
  807:   T_student *first_student,*a_student;
  808:   int result;
  809: 
  810:   result=capa_get_section(&first_student,0);
  811:   
  812:   if ( result == 0 ) { 
  813:     Tcl_Eval(interp,"displayError \"There are no students in this class, you can only do random runs\"");
  814:     Tcl_ResetResult(interp);
  815:     return TCL_OK; 
  816:   } 
  817:   if ( result == -1 ) {
  818:     Tcl_Eval(interp,"displayError \"There is no classl file, you can only do random runs.\"");
  819:     Tcl_ResetResult(interp);
  820:     return TCL_OK; 
  821:   }
  822:   
  823:   a_student=first_student;
  824:   Tcl_ResetResult(interp);
  825:   while( a_student ) {
  826:     Tcl_AppendElement(interp,a_student->s_sn);
  827:     Tcl_AppendElement(interp,a_student->s_nm);
  828:     sprintf(buf,"%d",a_student->s_sec);
  829:     Tcl_AppendElement(interp,buf);
  830:     a_student=a_student->s_next;
  831:   }
  832:   free_students(first_student);
  833:   return TCL_OK;
  834: }
  835: 
  836: void capaShowParseLocation(int sigNum) 
  837: {
  838:   extern int Current_line[MAX_OPENED_FILE];
  839:   extern int Input_idx;
  840:   extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
  841:   extern Tcl_Interp *gInterp;
  842:   char buf[BUFFER_SIZE];
  843: 
  844:   sprintf(buf,"displayError \"In file %s on Line %d a coding error caused a fatal error in Quizzer.\"",Opened_filename[Input_idx],Current_line[Input_idx]-1);
  845:   printf(buf);
  846:   fflush(stdout);
  847:   Tcl_Eval(gInterp,buf);
  848:   exit(-1);
  849: }
  850: 
  851: void capaGenerateError()
  852: {
  853:   extern Tcl_Interp *gInterp;
  854:   char buf[BUFFER_SIZE];
  855: 
  856:   sprintf(buf, "displayError \"Your last action just caused Quizzer to die. Please let the developers know what action caused this. Thanks.\"");
  857:   printf(buf);
  858:   fflush(stdout);
  859:   Tcl_Eval(gInterp,buf);
  860:   exit(-1);
  861: }
  862: 
  863: /*
  864: extern int Input_idx;
  865: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
  866: extern char Current_line[MAX_OPENED_FILE];
  867: extern Tcl_Interp *gInterp;
  868: void dynamicStatus()
  869: {
  870:   char *buf,*buf2,small[BUFFER_SIZE];
  871:   int i,j,totlen=0,len,idx=0;
  872: 
  873:   for(i=0;i<=Input_idx;i++) totlen=+strlen(Opened_filename[i])+4;
  874:   buf=capa_malloc(sizeof(char),totlen);
  875:   for(i=0;i<=Input_idx;i++) {
  876:     len=strlen(Opened_filename[i]);
  877:     for(j=0;j<len;j++) buf[idx++] = Opened_filename[i][j];
  878:     buf[idx++] = ':';
  879:     sprintf(small,"%d",Current_line[i]);
  880:     len=strlen(small);
  881:     for(j=0;j<len;j++) buf[idx++] = small[j];
  882:     buf[idx++]=' ';
  883:     buf[idx]='\0';
  884:   }
  885:   buf[idx++]='\n';
  886:   buf[idx]='\0';
  887:   buf2=capa_malloc(sizeof(char),strlen(buf)*2);
  888:   j=capaPrepareBuffer(buf,buf2,0);
  889:   capa_mfree(buf);
  890:   buf=capa_malloc(sizeof(char),strlen(buf2)+BUFFER_SIZE);
  891:   sprintf(buf,"%s insert end %s",gPreviewText,buf2);
  892:   if (Tcl_Eval(gInterp,buf) != TCL_OK) {
  893:     fprintf(stderr,"Tcl_Eval error 2a\n");
  894:     fprintf(stderr,"%s\n",gInterp->result);
  895:   }
  896:   capa_mfree(buf);
  897:   capa_mfree(buf2);
  898: }
  899: */
  900: 
  901: void capaQuizzerStatus()
  902: {
  903:   static time_t lasttime;
  904:   time_t thistime=time(NULL);
  905:   if (thistime > lasttime) {
  906:     extern Tcl_Interp *gInterp;
  907:     char *buf=parser_status(),*buf2;
  908:     int j;
  909:     buf2=capa_malloc(sizeof(char),strlen(buf)*2);
  910:     j=capaPrepareBuffer(buf,buf2,0);
  911:     capa_mfree(buf);
  912:     buf=capa_malloc(sizeof(char),strlen(buf2)+BUFFER_SIZE);
  913:     if (gCreateDvi) {
  914:       sprintf(buf,"global gStopStatus;set gStopStatus \"%s\"",buf2);
  915:     } else {
  916:       sprintf(buf,"%s insert end \"%s\n\";%s see end",
  917: 	      gPreviewText,buf2,gPreviewText);
  918:     }
  919:     capa_mfree(buf2);
  920:     if (Tcl_Eval(gInterp,buf) != TCL_OK) {
  921:       fprintf(stderr,"Tcl_Eval error 2a\n");
  922:       fprintf(stderr,"%s\n",gInterp->result);
  923:     }
  924:     capa_mfree(buf);
  925:     while(Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT));
  926:     lasttime=time(NULL);
  927:   } else {
  928:     if (!gFasterParsing) while(Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT));
  929:   }
  930: }
  931: 
  932: void signalHandler(int sigNum)
  933: {
  934:   if (capaParsing) {
  935:     capaShowParseLocation(sigNum);
  936:   } else {
  937:     capaGenerateError();
  938:   }
  939: }
  940: 
  941: int capaStopParser(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  942: {
  943:   extern int Stop_Parser;
  944:   Stop_Parser=1;
  945:   return TCL_OK;
  946: }
  947: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>