File:  [LON-CAPA] / capa / capa51 / GUITools / grader.funct.c
Revision 1.5: download - view: text, annotated - select for diffs
Mon Aug 7 20:47:29 2000 UTC (23 years, 9 months ago) by albertel
Branches: MAIN
CVS tags: release_5-1-3, HEAD
- fixed license notices the reference the GNU GPL rather than the GNU LGPL

    1: /* interfaces to the C portions of CAPA for grader
    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 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:    General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU 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:  * grader.funct.c
   27:  * Guy Albertelli II 1996
   28:  */
   29: #include <stdio.h>
   30: #include <tk.h>
   31: #include <pProj/capaCommon.h>
   32: #include <grader.h>
   33: #include <common.h>
   34: #include <ctype.h>
   35: #include <time.h>
   36: 
   37: /*
   38:  * used to remeber the weights and partial credit from a parse for when 
   39:  * setting a DBHeader
   40:  */
   41: 
   42: /* Reads a header form the file and sets up the time and date variables
   43:  */ 
   44: int capaGetHeader(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
   45: {
   46:   T_header header;
   47:   char * setNumber,buf[BUFFER_SIZE],*sectionNumber,dateStr[BUFFER_SIZE];
   48:   int set,section,result;
   49: 
   50: 
   51:   setNumber=Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY);
   52:   sectionNumber=Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY);
   53: 
   54:   if ( setNumber[0] == '\0' )  return TCL_OK;
   55:   if ( sectionNumber[0] == '\0' )  return TCL_OK;
   56: 
   57:   set=atoi(setNumber);
   58:   section=atoi(sectionNumber);
   59: 
   60:   result=capa_get_header(&header,set);
   61: 
   62:   if ( result == -1 )
   63:     {
   64:       Tcl_ResetResult(interp);
   65:       Tcl_AppendElement(interp,"0");
   66:       return TCL_OK;
   67:     }
   68: 
   69:   result=capa_get_date(CHECK_OPEN_DATE,NULL,section,set,dateStr);
   70:   if (result<0) {
   71:     Tcl_ResetResult(interp);
   72:     Tcl_AppendElement(interp,"-1");
   73:     return TCL_OK;
   74:   }
   75:   sscanf(dateStr,"%10c",buf);
   76:   buf[10]='\0';
   77:   Tcl_SetVar(interp,"gOpenDate",buf,TCL_GLOBAL_ONLY);
   78:   sscanf((dateStr)+11,"%5c",buf);
   79:   buf[5]='\0';
   80:   Tcl_SetVar(interp,"gOpenTime",buf,TCL_GLOBAL_ONLY);
   81: 
   82:   result=capa_get_date(CHECK_DUE_DATE,NULL,section,set,dateStr);
   83:   if (result<0) {
   84:     Tcl_ResetResult(interp);
   85:     Tcl_AppendElement(interp,"-1");
   86:     return TCL_OK;
   87:   }
   88:   sscanf(dateStr,"%10c",buf);
   89:   buf[10]='\0';
   90:   Tcl_SetVar(interp,"gDueDate",buf,TCL_GLOBAL_ONLY);
   91:   sscanf((dateStr)+11,"%5c",buf);
   92:   buf[5]='\0';
   93:   Tcl_SetVar(interp,"gDueTime",buf,TCL_GLOBAL_ONLY);
   94: 
   95:   result=capa_get_date(CHECK_ANS_DATE,NULL,section,set,dateStr);
   96:   if (result<0) {
   97:     Tcl_ResetResult(interp);
   98:     Tcl_AppendElement(interp,"-1");
   99:     return TCL_OK;
  100:   }
  101:   sscanf(dateStr,"%10c",buf);
  102:   buf[10]='\0';
  103:   Tcl_SetVar(interp,"gAnswerDate",buf,TCL_GLOBAL_ONLY);
  104:   sscanf((dateStr)+11,"%5c",buf);
  105:   buf[5]='\0';
  106:   Tcl_SetVar(interp,"gAnswerTime",buf,TCL_GLOBAL_ONLY);
  107:   
  108:   Tcl_ResetResult(interp);
  109:   Tcl_AppendElement(interp,"1");
  110:   capa_mfree(header.weight);
  111:   capa_mfree(header.partial_credit);
  112:   return TCL_OK;
  113: }
  114: 
  115: /* get the information for all of the students in the current section
  116:  * and puts them into the listbox.
  117:  * Arguments: the name of the variable the widget name of the listbox
  118:  * is in.
  119:  */
  120: int capaGetStudents(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  121: {
  122:   T_student *headStudent,*currentStudent;
  123:   int result,section,set,setScore,maxScore,num=0;
  124:   char buf[BUFFER_SIZE],buf2[BUFFER_SIZE],*answers,*listWidget;
  125:   
  126:   section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY));
  127:   set=atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY));
  128:   
  129:   if ( (listWidget = Tcl_GetVar(interp,argv[1],
  130: 				 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)
  131:     {
  132:       fprintf(stderr,"Tcl_GetVar error\n");
  133:       fprintf(stderr,"%s\n",interp->result);
  134:       return TCL_ERROR;
  135:     }
  136: 
  137:   result=capa_sorted_section(&headStudent,section);
  138: 
  139:   if (result == -1 || result == 0)
  140:     {
  141:       Tcl_Eval(interp,"displayError \"Invalid section\"");
  142:       Tcl_ResetResult(interp);
  143:       return TCL_OK;
  144:     }
  145: 
  146:   currentStudent=headStudent;
  147: 
  148:   while(currentStudent!=NULL)
  149:     {
  150:       num++;
  151:       setScore = capa_get_score(currentStudent->s_sn,set,&maxScore,&answers);
  152:       if ( setScore == -1 ) setScore=0;
  153:       sprintf(buf,"%s %s   %2d/%2d      %2d      ",currentStudent->s_nm,
  154: 	      currentStudent->s_sn,setScore,maxScore,
  155: 	      capa_PIN(currentStudent->s_sn,set,0));
  156:       
  157:       capaPrepareBuffer(buf,buf2,0);
  158:       sprintf(buf,"%s insert end \"%s\" ",listWidget,buf2);
  159:       
  160:       if (Tcl_Eval(interp,buf) != TCL_OK)
  161: 	{
  162: 	  fprintf(stderr,"Tcl_Eval error\n");
  163: 	  fprintf(stderr,"%s\n",interp->result);
  164: 	  free_students(headStudent);
  165: 	  return TCL_ERROR;
  166: 	}
  167:       
  168:       if (!(num%10)) {
  169: 	if (Tcl_Eval(interp,"update") != TCL_OK)
  170: 	  {
  171: 	    fprintf(stderr,"Tcl_Eval error\n");
  172: 	    fprintf(stderr,"%s\n",interp->result);
  173: 	    free_students(headStudent);
  174: 	    return TCL_ERROR;
  175: 	  }
  176:       }
  177:       currentStudent=currentStudent->s_next;
  178:       capa_mfree(answers);
  179:     }
  180: 
  181:   free_students(headStudent);
  182:   if (!(num%5)) {
  183:     if (Tcl_Eval(interp,"update") != TCL_OK)
  184:       {
  185: 	fprintf(stderr,"Tcl_Eval error\n");
  186: 	fprintf(stderr,"%s\n",interp->result);
  187: 	return TCL_ERROR;
  188:       }
  189:   }
  190:   return TCL_OK;
  191: }
  192: 
  193: /* searches for the section a student is in by either name or number
  194:  * Arguments: one of (name or number) and then the name or number to
  195:  * search for.
  196:  */
  197: int capaFindSection(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  198: { 
  199:   int   errorNm;
  200:   char  searchStr[MAX_NAME_CHAR+1],buf[MAX_NAME_CHAR+1];
  201:   T_student student;
  202:   
  203:   switch(argv[1][1])
  204:     {
  205:       case 'a':
  206: 	strncpy(searchStr,argv[2],MAX_NAME_CHAR+1);
  207: 	if ( (errorNm = capa_student_byname(searchStr,&student ))==0 ) 
  208: 	  {
  209: 	    sprintf(buf,"%d",0);
  210: 	  }
  211: 	else
  212: 	  {
  213: 	    sprintf(buf,"%d",student.s_sec);
  214: 	  }
  215: 	break;
  216:     case 'u':
  217: 	strncpy(searchStr,argv[2],MAX_NAME_CHAR+1);
  218: 	if ( (errorNm = capa_get_student(searchStr,&student ))==0 ) 
  219: 	  {
  220: 	    sprintf(buf,"%d",0);
  221: 	  }
  222: 	else
  223: 	  {
  224: 	    sprintf(buf,"%d",student.s_sec);
  225: 	  }      
  226:       break;
  227:     default:
  228:       break;
  229:     }
  230:   Tcl_ResetResult(interp);
  231:   Tcl_AppendElement(interp,buf);
  232:   return TCL_OK;
  233: }
  234: 
  235: /* makes a student report
  236:  * Arguments: the student number
  237:  */
  238: int capaGetReportInfo(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  239: {
  240:   char          studentNumber[MAX_STUDENT_NUMBER+1], 
  241:                 lineOne[BUFFER_SIZE],*wgt,*partialCredit;
  242:   T_header      header;
  243:   T_entry       entry;
  244:   int		ii, setIdx, setScores, setValids, 
  245:                 totalSet, totalProbs, neverLogin;
  246:   int           termScores, termValids;
  247: 
  248:   strncpy(studentNumber,argv[1], MAX_STUDENT_NUMBER+1);
  249:   totalSet  = howManySetDBFile();
  250: 
  251:   Tcl_ResetResult(interp);
  252: 
  253:   for(termScores=0,termValids=0,setIdx=1;setIdx <= totalSet ;setIdx++) 
  254:     {
  255:       capa_get_entry(&entry, studentNumber, setIdx);
  256:       totalProbs = entry.e_probs;
  257:       if( capa_get_header( &header, setIdx ) == -1 ) 
  258: 	{
  259: 	  Tcl_ResetResult(interp);
  260: 	  Tcl_AppendElement(interp,"File Error");
  261: 	  return TCL_OK;
  262: 	}
  263:       wgt=header.weight;
  264:       partialCredit=header.partial_credit;
  265: 
  266:       for(setScores=0, setValids=0,neverLogin=1,ii=0;ii<totalProbs;ii++) 
  267: 	{
  268: 	  switch(entry.answers[ii]) 
  269: 	    { 
  270: 	    case 'Y': case 'y':  
  271: 	      neverLogin = 0;
  272: 	      setScores    += (wgt[ii] - '0'); 
  273: 	      setValids    += (wgt[ii] - '0');  
  274: 	      break; 
  275: 	    case '-': case 'N': case 'n': 
  276: 	      setValids    += (wgt[ii] - '0');  
  277: 	      break; 
  278: 	    case 'E': case 'e':
  279: 	      break;
  280: 	    default : 
  281: 	      if( entry.answers[ii] >= '0' && entry.answers[ii] <= '9' ) 
  282: 		{
  283: 		  setScores    += (entry.answers[ii] - '0');
  284: 		  setValids    += (wgt[ii] - '0');
  285: 		  neverLogin = 0;
  286: 		} 
  287: 	      break;
  288: 	    } 
  289: 	}
  290:       entry.answers[totalProbs]='\0'; /* get rid of last unknown chars */
  291:       entry.tries[3*totalProbs]='\0';
  292:       termScores += setScores;
  293:       termValids += setValids;
  294:     
  295:       if(neverLogin) 
  296: 	{
  297: 	  sprintf(lineOne,"%3d   -/%3d %s\n",setIdx,setValids,entry.answers);
  298: 	} 
  299:       else 
  300: 	{
  301: 	  sprintf(lineOne,"%3d %3d/%3d %s\n",setIdx,setScores,setValids,entry.answers);
  302: 	}
  303:       Tcl_AppendResult(interp,lineOne,NULL);
  304:       sprintf(lineOne,"           %s\n",entry.tries);
  305:       Tcl_AppendResult(interp,lineOne,NULL);
  306:       capa_mfree(entry.answers);
  307:       capa_mfree(entry.tries);
  308:     }
  309:   sprintf(lineOne,"========================\n   Total = %3d/%3d",termScores,termValids);
  310:   Tcl_AppendResult(interp,lineOne,NULL);
  311:   capa_mfree(header.weight);
  312:   capa_mfree(header.partial_credit);
  313:   return TCL_OK;
  314: }
  315: 
  316: int compare_string( a, b)
  317: char *a, *b;
  318: {
  319:   return( strcasecmp(a, b) );
  320: }
  321: 
  322: /* Builds a set summary
  323:  * Argument: the filename to write to
  324:  */
  325: int capaGetSetSummary(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  326: {   
  327:   T_student *stuPtr, *currentStudentPtr;
  328:   T_header   a_header;
  329:   int        section, set;
  330:   int        studentCount,currentStudent, setScores, validScores;
  331:   char      fmt1[64], fmt2[64],buf[BUFFER_SIZE],*str1="Student Name",*str2=" ";
  332:   char      *answersPtr;
  333:   FILE      *outputFile;
  334: 
  335:   section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY));
  336:   set=atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY));
  337:   Tcl_ResetResult(interp);
  338: 
  339:   studentCount = capa_sorted_section(&stuPtr, section);
  340:   if( studentCount > 0 ) 
  341:     {
  342:       if( capa_get_header( &a_header, set) == -1 ) 
  343: 	{
  344: 	  Tcl_Eval(interp,"displayerror \"Cannot open set.db file\"");
  345: 	  Tcl_ResetResult(interp);
  346: 	  free_students(stuPtr);
  347: 	  return TCL_OK;
  348: 	}
  349:       capa_mfree(a_header.weight);
  350:       capa_mfree(a_header.partial_credit);
  351:       sprintf(fmt1,"%%-%ds\t%%%ss\t Score\n", MAX_NAME_CHAR,a_header.num_questions);
  352: 
  353:       outputFile=fopen(argv[1],"w");
  354:       fprintf(outputFile, "Section %-3d, Set %-3d Score Report\n",section, set);
  355: 
  356:       fprintf(outputFile, fmt1,str1,str2);
  357: 
  358:       sprintf(fmt1,"%%-%ds\t%%s\t  -/%%3d\n", MAX_NAME_CHAR);
  359:       sprintf(fmt2,"%%-%ds\t%%s\t%%3d/%%3d\n", MAX_NAME_CHAR);
  360: 
  361:       for(currentStudentPtr=stuPtr,currentStudent=0;currentStudentPtr;
  362: 	  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
  363: 	{
  364: 	  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
  365: 	  Tcl_Eval(interp,buf);
  366: 	  if( (setScores = capa_get_score(currentStudentPtr->s_sn,
  367: 					  set,&validScores,&answersPtr) ) == -2 ) 
  368: 	    {
  369: 	      Tcl_Eval(interp,"displayerror \"Cannot open set.db file\"");
  370: 	      Tcl_ResetResult(interp);
  371: 	      free_students(stuPtr);
  372: 	      capa_mfree(answersPtr);
  373: 	      fclose(outputFile);
  374: 	      return TCL_OK;
  375: 	    }
  376: 	  if( setScores < 0 ) 
  377: 	    {
  378: 	      fprintf(outputFile,fmt1,currentStudentPtr->s_nm,answersPtr,validScores );
  379: 	    } 
  380:           else 
  381: 	    {
  382: 	      fprintf(outputFile,fmt2,currentStudentPtr->s_nm,answersPtr,setScores,validScores );
  383: 	    }
  384: 	  capa_mfree(answersPtr);
  385: 	}
  386:       free_students(stuPtr);
  387:       fclose(outputFile);
  388:     }
  389:   return TCL_OK;
  390: }
  391: 
  392: /* builds a term summary
  393:  * Arguments: filename
  394:  */
  395: int capaGetTermSummary(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  396: {
  397:   T_student *studentPtr, *currentStudentPtr;
  398:   int        section, totalSet;
  399:   int        setIndex, setScores, termScores, validScores, termValids;
  400:   int        studentCount,currentStudent=1;
  401:   char       fmt[64];
  402:   char      *answersPtr,buf[BUFFER_SIZE];
  403:   FILE      *outputFile;
  404: 
  405:   outputFile=fopen(argv[1],"w");
  406:   section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY));
  407:   totalSet  = howManySetDBFile();
  408:   Tcl_ResetResult(interp);
  409: 
  410:   studentCount = capa_sorted_section(&studentPtr, section);
  411:   if( studentCount > 0 ) 
  412:     {
  413:       for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
  414: 	  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
  415: 	{
  416: 	  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
  417: 	  Tcl_Eval(interp,buf);
  418: 	  sprintf(fmt,"%%-%ds\n", MAX_NAME_CHAR);
  419: 	  fprintf(outputFile,fmt,currentStudentPtr->s_nm);
  420: 
  421: 	  for( termScores = 0, termValids = 0, setIndex = 1; setIndex <= totalSet; setIndex++) 
  422: 	    {
  423: 	      if( (setScores = capa_get_score(currentStudentPtr->s_sn,
  424: 					      setIndex,&validScores,&answersPtr) ) == -2 ) 
  425: 		{
  426: 		  sprintf(buf,"displayerror \"Cannot open set%d.db file\"",setIndex);
  427: 		  Tcl_Eval(interp,buf);
  428: 		  Tcl_ResetResult(interp);
  429: 		  capa_mfree(answersPtr);
  430: 		  free_students(studentPtr);
  431: 		  fclose(outputFile);
  432: 		  return TCL_OK;
  433: 		}
  434: 	      if( setScores < 0 ) 
  435: 		{
  436: 		  fprintf(outputFile,"Set %-3d\t%s\t  -/%3d\n", setIndex,answersPtr, validScores);
  437: 		} 
  438:               else 
  439: 		{
  440: 		  fprintf(outputFile, "Set %-3d\t%s\t%3d/%3d\n",
  441: 			   setIndex,answersPtr,setScores,validScores );
  442: 		  termScores += setScores;
  443: 		}
  444: 	      capa_mfree(answersPtr);
  445: 	      termValids += validScores; 
  446: 	    }
  447: 	  fprintf(outputFile,"\t\t\tTerm Score = %3d/%3d\n", termScores,termValids);
  448: 	  fprintf(outputFile, "-----------------------------------------------------------------------\n");
  449: 	}
  450:       free_students(studentPtr);
  451:     }
  452:   fclose(outputFile);
  453:   return TCL_OK;
  454: }
  455: 
  456: extern int Parsemode_f;
  457: 
  458: /* runs capaParse and puts the results into a text widget
  459:  * Arguments: the name it is registered under (enscriptParse, texParse,
  460:  *            webParse, bubblerParse); what results of the parse to show
  461:  *            0 (Problem Only), 1 (Question and Answer), 2 (Answer Only);
  462:  *            the set number; either (Random or Specific) student; section;
  463:  *            student Number; student Name ; the name of the variable to
  464:  *            find the widget name of the text widget to put the text into
  465:  */
  466: int capaTclParse (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  467: {
  468:   extern  char      *EndText_p;
  469:   T_student student;
  470:   Problem_t *headProblem,*currentProblem;
  471:   int numOfQuestions,numAnswers,problemNumber=0;
  472:   int result,i=1,j,length;
  473:   char *buf, *buf2, *temp, *previewText=NULL;
  474:   char lower[32],upper[32],ans[32], unit[32];
  475:   double  targetAns;
  476:   int  c_set;
  477: #ifdef GRADER_UPDATE
  478:   char *update=";update";
  479: #else
  480:   char *update=" ";
  481: #endif
  482: 
  483:   switch(argv[0][0])
  484:     {
  485:     case 'e':Parsemode_f = ASCII_MODE;break;
  486:     case 't':Parsemode_f = TeX_MODE;break;
  487:     case 'w':Parsemode_f = HTML_MODE;break;
  488:     case 'b':Parsemode_f = BUBBLE_MODE;break;
  489:     default:
  490:       Tcl_ResetResult(interp);
  491:       Tcl_AppendElement(interp,"Invalid call to capaTclParse\n");
  492:       return TCL_ERROR;
  493:       break;
  494:     }
  495: 
  496:   if ( (previewText = Tcl_GetVar(interp,argv[7],
  497: 				 TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)
  498:     {
  499:       fprintf(stderr,"Tcl_GetVar error\n");
  500:       fprintf(stderr,"%s\n",interp->result);
  501:       return TCL_ERROR;
  502:     }
  503:   c_set = atoi(argv[2]);
  504:   switch (argv[3][0])
  505:     {
  506:     case 'R':
  507:       result = capa_pick_student(atoi(argv[4]),&student);
  508:       if (result == -1)
  509: 	{
  510: 	  buf=capa_malloc(BUFFER_SIZE,1);
  511: 	  sprintf(buf,"displayError \"There are no students in section %d.\"",
  512: 		  atoi(argv[4]));
  513: 	  Tcl_Eval(interp,buf);
  514: 	  capa_mfree(buf);
  515: 	  Tcl_ResetResult(interp);
  516: 	  Tcl_AppendElement(interp,"-1");
  517: 	  return TCL_OK;
  518: 	}
  519:       
  520:       result = capa_parse(atoi(argv[2]),&headProblem,student.s_sn,&numOfQuestions,NULL);
  521:       break;
  522:     case 'S':
  523:       result = capa_get_student(argv[5],&student);
  524:       if ((result == -1) || (result == 0))
  525: 	{
  526: 	  buf=capa_malloc(BUFFER_SIZE,1);
  527: 	  sprintf(buf,"displayError \"The student %s does not exist.\"",
  528: 		  argv[5]);
  529: 	  Tcl_Eval(interp,buf);
  530: 	  capa_mfree(buf);
  531: 	  Tcl_ResetResult(interp);
  532: 	  Tcl_AppendElement(interp,"-1");
  533: 	  return TCL_OK;
  534: 	}
  535:       result = capa_parse(atoi(argv[2]),&headProblem,argv[5],&numOfQuestions,NULL);
  536:       break;
  537:     default:
  538:       Tcl_ResetResult(interp);
  539:       Tcl_AppendElement(interp,"Invalid 2nd argument to capaTclParse\n");
  540:       return TCL_ERROR;
  541:       break;
  542:     }
  543: 
  544:   if (result==-1)
  545:     {
  546:       Tcl_ResetResult(interp);
  547:       Tcl_AppendElement(interp,"-1");
  548:       return TCL_OK;
  549:     }
  550: 
  551:   currentProblem=headProblem;
  552:     
  553:   if(argv[1][0] == Q_ANSWER)
  554:     {
  555:       /*
  556:       switch(Parsemode_f)
  557: 	{
  558: 	case ASCII_MODE:
  559: 	  sprintf(buf,"Section %d                               Set %d\n Name: %s    PIN: %d\n\n",
  560: 		  student.s_sec, atoi(argv[2]), student.s_nm,
  561: 		  capa_PIN(student.s_sn, atoi(argv[2]),0));
  562: 	  break;
  563: 	case TeX_MODE:
  564: 	  sprintf(buf,"{\\bf Section %d\\qquad Set %d}\\\\\\medskip \n{\\bf Name: \
  565: %s\\qquad PIN: %d}\\\\ \\bigskip\n\n", student.s_sec, atoi(argv[2]), student.s_nm,
  566: 		  capa_PIN(student.s_sn, atoi(argv[2]),0));
  567: 	  break;
  568: 	case HTML_MODE:
  569: 	  sprintf(buf,"Section %d                               Set %d\n Name: %s    PIN: %d\n\n",
  570: 		  student.s_sec, atoi(argv[2]), student.s_nm,
  571: 		  capa_PIN(student.s_sn, atoi(argv[2]),0));
  572: 	  break;
  573: 	case BUBBLE_MODE:
  574: 	  break;
  575: 	}
  576:       j=capaPrepareBuffer(buf,buf2,0);
  577: 
  578:       sprintf(buf,"%s insert end \" %s \" header",previewText,buf2);
  579: 
  580:       if (Tcl_Eval(interp,buf) != TCL_OK)
  581: 	{
  582: 	  fprintf(stderr,"Tcl_Eval error\n");
  583: 	  fprintf(stderr,"%s\n",interp->result);
  584: 	  return TCL_ERROR;
  585: 	}
  586:      */
  587:     }
  588: 
  589:   while (currentProblem!=NULL)
  590:     {
  591:       switch (argv[1][0])
  592: 	{
  593: 	case Q_PROBLEM:
  594: 	  if (currentProblem->question) { 
  595: 	    length=strlen(currentProblem->question); 
  596: 	  } else { 
  597: 	    length=0;
  598: 	  }
  599: 	  buf=capa_malloc(BUFFER_SIZE+(2*length),1);
  600: 	  buf2=capa_malloc(BUFFER_SIZE+(2*length),1);
  601: 	  if(currentProblem->question) {
  602: 	    j=capaPrepareBuffer(currentProblem->question,buf2,0);
  603: 	    buf2[j-1]='\n';
  604: 	    buf2[j]='\0';
  605: 	  } else {
  606: 	    buf2[0]='\n';buf2[1]='\0';
  607: 	  }
  608: 	  if(currentProblem->question) {
  609: 	    j=capaPrepareBuffer(currentProblem->question,buf2,0);
  610: 	    buf2[j-1]='\n';
  611: 	    buf2[j]='\0';
  612: 	  } else {
  613: 	    buf2[0]='\n';buf2[1]='\0';
  614: 	  }
  615: 
  616: 	  switch(Parsemode_f)
  617: 	    {
  618: 	    case ASCII_MODE:
  619: 	      sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem",
  620: 		      previewText,buf2);
  621: 	      break;
  622: 	    case TeX_MODE:
  623: 	      sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2);
  624: 	      break;
  625: 	    case HTML_MODE:
  626: 	      sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2);
  627: 	      break;
  628: 	    case BUBBLE_MODE:
  629: 	      break;
  630: 	    }	      
  631: 	  if (Tcl_Eval(interp,buf) != TCL_OK)
  632: 	    {
  633: 	      fprintf(stderr,"Tcl_Eval error\n");
  634: 	      fprintf(stderr,"%s\n",interp->result);
  635: 	      return TCL_ERROR;
  636: 	    }
  637: 	  capa_mfree(buf);
  638: 	  capa_mfree(buf2);
  639: 	  break;
  640: 	case Q_PROBLEM_AND_ANSWER:
  641: 	  if (currentProblem->question) { 
  642: 	    length=strlen(currentProblem->question); 
  643: 	  } else { 
  644: 	    length=0;
  645: 	  }
  646: 	  buf=capa_malloc(BUFFER_SIZE+(2*length),1);
  647: 	  buf2=capa_malloc(BUFFER_SIZE+(2*length),1);
  648: 	  temp=capa_malloc(BUFFER_SIZE+(2*length),1);
  649: 	  j=capaPrepareBuffer(currentProblem->question,buf2,0);
  650: 
  651: 	  switch(Parsemode_f)
  652: 	    {
  653: 	    case ASCII_MODE:
  654: 	      sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem",
  655: 		      previewText,buf2);
  656: 	      break;
  657: 	    case TeX_MODE:
  658: 	      sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2);
  659: 	      break;
  660: 	    case HTML_MODE:
  661: 	      sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2);
  662: 	      break;
  663: 	    case BUBBLE_MODE:
  664: 	      break;
  665: 	    }
  666: 	  if (Tcl_Eval(interp,buf) != TCL_OK)
  667: 	    {
  668: 	      fprintf(stderr,"Tcl_Eval error\n");
  669: 	      fprintf(stderr,"%s\n",interp->result);
  670: 	      return TCL_ERROR;
  671: 	    }
  672: 
  673: 	  capa_mfree(buf);
  674: 	  capa_mfree(buf2);
  675: 	  capa_mfree(temp);
  676: 	  capaInsertAnswer(currentProblem,interp,previewText);
  677: 	  break;
  678: 	case Q_ANSWER:
  679: 	  print_begin_item(Parsemode_f,interp,previewText,problemNumber+1);
  680: 	  capaInsertAnswer(currentProblem,interp,previewText);
  681: 	  break;
  682: 	}
  683: 
  684:       currentProblem=currentProblem->next;
  685:       problemNumber++;
  686:     }
  687:   if( ( EndText_p != NULL) ) 
  688:     {
  689:       buf=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  690:       buf2=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  691:       temp=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1);
  692:       sprintf(temp,"%s", EndText_p);
  693:       j=capaPrepareBuffer(temp,buf2,0);
  694:       
  695:       sprintf(buf,"%s insert end \"%s\" answer%s",previewText,buf2,update);
  696:       
  697:       if (Tcl_Eval(interp,buf) != TCL_OK)
  698:         {
  699: 	  fprintf(stderr,"Tcl_Eval error 7\n");
  700: 	  fprintf(stderr,"%s\n",interp->result);
  701: 	  return TCL_ERROR;
  702: 	}
  703:       capa_mfree(buf);
  704:       capa_mfree(buf2);
  705:       capa_mfree(temp);
  706:     }
  707:   free_problems(headProblem);
  708:   
  709:   if (result==0) 
  710:     {
  711:       Tcl_ResetResult(interp);
  712:       Tcl_AppendElement(interp,"0");
  713:     }
  714:   else
  715:     {
  716:       buf=capa_malloc(BUFFER_SIZE,1);
  717:       sprintf(buf,"%d",result);
  718:       Tcl_ResetResult(interp);
  719:       Tcl_AppendElement(interp,buf);
  720:       capa_mfree(buf);
  721:     }
  722:   
  723:   return TCL_OK;
  724: }
  725: 
  726: /* setup gQuestionType for all of the questions
  727:  * Arguments: number of Questions
  728:  */
  729: int capaGetQuestionTypes(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  730: {
  731:   int numQuestions,result,i;
  732:   T_header header;
  733:   char buf[BUFFER_SIZE], buf2[BUFFER_SIZE],*weight;
  734: 
  735:   if (argc != 2) 
  736:     {
  737:       Tcl_ResetResult(interp);
  738:       Tcl_AppendResult(interp,"Wrong number of arguments to getQuestionTypes",
  739: 		       NULL);
  740:       return TCL_ERROR;
  741:     }
  742:   
  743:   numQuestions=atoi(argv[1]);
  744:   
  745:   result = capa_get_header(&header,atoi(Tcl_GetVar(interp,"gSetLoad",
  746: 						   TCL_GLOBAL_ONLY)));
  747:   weight=header.weight;
  748: 			   
  749:   if (result == -1)
  750:     {
  751:       Tcl_ResetResult(interp);
  752:       Tcl_AppendResult(interp,"capa_get_header returned error.",NULL);
  753:       return TCL_ERROR;
  754:     }
  755:   
  756:   for(i=1;i<=numQuestions;i++)
  757:     {
  758:       sprintf(buf,"%d",i);
  759:       switch(header.partial_credit[i-1])
  760: 	{
  761: 	case '0':
  762: 	  Tcl_SetVar2(interp,"gQuestionType",buf,"autoGrade",TCL_GLOBAL_ONLY);
  763: 	  break;
  764: 	case '1':
  765: 	  Tcl_SetVar2(interp,"gQuestionType",buf,"handGrade",TCL_GLOBAL_ONLY);
  766: 	  sprintf(buf,"max%d",i);
  767: 	  sprintf(buf2,"%c",weight[i-1]);
  768: 	  Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY);
  769: 	  break;
  770: 	default:
  771: 	  Tcl_ResetResult(interp);
  772: 	  Tcl_AppendResult(interp,"Header for the set.db file is incorrect.",
  773: 			   NULL);
  774: 	  return TCL_ERROR;
  775: 	  break;
  776: 	}
  777:     }
  778:   capa_mfree(header.weight);
  779:   capa_mfree(header.partial_credit);
  780:   Tcl_ResetResult(interp);
  781:   return TCL_OK;
  782: }
  783: 
  784: /* setup gAnswer for all of the questions
  785:  * Arguments: number of Questions
  786:  */
  787: T_entry graderEntry;
  788: int capaSetupGAnswer (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  789: {
  790:   int numQuestions,i,result;
  791:   char buf[BUFFER_SIZE],buf2[BUFFER_SIZE],*questionType;
  792: 
  793:   if (argc != 2) 
  794:     {
  795:       Tcl_ResetResult(interp);
  796:       Tcl_AppendResult(interp,"Incorrect number of arguments to setup gAnswer",
  797: 		       NULL);
  798:       return TCL_ERROR;
  799:     }
  800: 
  801:   numQuestions=atoi(argv[1]);
  802: 
  803:   result = capa_get_entry(&graderEntry,Tcl_GetVar2(interp,"gGrading","number",
  804: 					     TCL_GLOBAL_ONLY),
  805: 			  atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY)));
  806: 
  807:   if (result == 0)
  808:     {
  809:       Tcl_ResetResult(interp);
  810:       Tcl_AppendResult(interp,"capa_get_entry returned error.",NULL);
  811:       return TCL_ERROR;
  812:     }
  813:   for(i=1;i<=numQuestions;i++)
  814:     {
  815:       sprintf(buf,"%d.tries",i);
  816:       buf2[0]=graderEntry.tries[(i-1)*3];buf2[1]=graderEntry.tries[(i-1)*3+1];
  817:       buf2[2]='\0';
  818:       Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY);
  819:       sprintf(buf,"%d",i);
  820:       switch(graderEntry.answers[i-1])
  821: 	{
  822: 	case '-':
  823: 	  Tcl_SetVar2(interp,"gAnswer",buf,"-",TCL_GLOBAL_ONLY);
  824: 	  break;
  825: 	case 'y':
  826: 	case 'n':
  827: 	case 'E':
  828: 	  sprintf(buf2,"%c",graderEntry.answers[i-1]);
  829: 	  Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY);
  830: 	  break;
  831: 	case 'Y':
  832: 	  sprintf(buf2,"%c",graderEntry.answers[i-1]);
  833: 	  Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY);
  834: 	  questionType=Tcl_GetVar2(interp,"gQuestionType",buf,
  835: 				   TCL_GLOBAL_ONLY);
  836: 	  switch(questionType[0])
  837: 	    {
  838: 	    case 'a':
  839: 	      sprintf(buf,"$gGradeCanvas.dash%d configure -state disabled",i);
  840: 	      if (Tcl_Eval(interp,buf)!=TCL_OK) 
  841: 		return TCL_ERROR;
  842: 	      sprintf(buf,"$gGradeCanvas.y%d configure -state disabled",i);
  843: 	      if (Tcl_Eval(interp,buf)!=TCL_OK) 
  844: 		return TCL_ERROR;
  845: 	      sprintf(buf,"$gGradeCanvas.n%d configure -state disabled",i);
  846: 	      if (Tcl_Eval(interp,buf)!=TCL_OK) 
  847: 		return TCL_ERROR;
  848: 	      sprintf(buf,"$gGradeCanvas.e%d configure -state disabled",i);
  849: 	      if (Tcl_Eval(interp,buf)!=TCL_OK) 
  850: 		return TCL_ERROR;
  851: 	      break;
  852: 	    case 'h':
  853: 	      sprintf(buf,"$gGradeCanvas.hand%d configure -state disabled",i);
  854: 	      if (Tcl_Eval(interp,buf)!=TCL_OK) 
  855: 		return TCL_ERROR;
  856: 	      break;
  857: 	    default:
  858: 	      Tcl_ResetResult(interp);
  859: 	      Tcl_AppendElement(interp,"questionType contains invlaid data in capaSetupGAnswer.");
  860: 	      return TCL_ERROR;
  861: 	      break;
  862: 	    }
  863: 	  break;
  864: 	default:
  865: 	  sprintf(buf2,"%c",graderEntry.answers[i-1]);
  866: 	  Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY);
  867: 	  break;
  868: 	}
  869:     }
  870: 
  871:   Tcl_ResetResult(interp);
  872:   return TCL_OK;
  873: }
  874: 
  875: /* save gAnswer to the set.db file
  876:  * Arguments: number of Questions
  877:  */
  878: int capaSaveGAnswer (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  879: {
  880:   T_entry entry;
  881:   int numQuestions,i,result;
  882:   char buf[BUFFER_SIZE],*gAnswer;
  883: 
  884:   if (argc != 2) 
  885:     {
  886:       Tcl_ResetResult(interp);
  887:       Tcl_AppendResult(interp,"Incorrect number of arguments to save gAnswer",NULL);
  888:       return TCL_ERROR;
  889:     }
  890: 
  891:   numQuestions=atoi(argv[1]);
  892: 
  893:   entry.answers=capa_malloc(numQuestions+1,1);
  894:   entry.tries=capa_malloc(3*numQuestions+1,1);
  895: 
  896:   for(i=0;i<numQuestions;i++) {
  897:     sprintf(buf,"%d",i+1);
  898:     gAnswer=Tcl_GetVar2(interp,"gAnswer",buf,TCL_GLOBAL_ONLY);
  899:     if ( gAnswer[0] != graderEntry.answers[i] ) {
  900:       entry.answers[i]=gAnswer[0];
  901:     } else {
  902:       entry.answers[i]='?';
  903:     }
  904:     sprintf(buf,"%d.tries",i+1);
  905:     gAnswer=Tcl_GetVar2(interp,"gAnswer",buf,TCL_GLOBAL_ONLY);
  906:     if (atoi(gAnswer) != atoi(&(graderEntry.tries[i*3]))) {
  907:       sprintf(&(entry.tries[i*3]),"%2d",atoi(gAnswer));
  908:       if (i<numQuestions-1) entry.tries[i*3+2]=',';
  909:     } else {
  910:       entry.tries[i*3]='-';entry.tries[i*3+1]='1';
  911:       if (i<numQuestions-1) entry.tries[i*3+2]=',';
  912:     }
  913:   }
  914:   entry.answers[numQuestions]='\0';
  915:   entry.tries[numQuestions*3]='\0';
  916:   sprintf(entry.student_number,Tcl_GetVar2(interp,"gGrading","number",TCL_GLOBAL_ONLY));
  917:   entry.e_probs=numQuestions;
  918:   result = capa_change_entry(&entry,Tcl_GetVar2(interp,"gGrading","number",
  919: 						TCL_GLOBAL_ONLY),
  920: 			     atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY)));
  921: 
  922:   if (result == -1) {
  923:     Tcl_ResetResult(interp);
  924:     Tcl_AppendResult(interp,"capa_change_entry returned an error.",NULL);
  925:     return TCL_ERROR;
  926:   }
  927: 
  928:   Tcl_ResetResult(interp);
  929:   return TCL_OK;
  930: }
  931: 
  932: /* a wrapper for capa_excuse
  933:  * Arguments: set; problem; section
  934:  */
  935: int capaExcuse (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  936: {
  937:   int result;
  938: 
  939:   result = capa_excuse(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]));
  940: 
  941:   if (result == -1)
  942:     {
  943:       Tcl_ResetResult(interp);
  944:       Tcl_AppendResult(interp,"capa_excuse returned error.",NULL);
  945:       return TCL_ERROR;
  946:     }
  947: 
  948:   return TCL_OK;
  949: }
  950: 
  951: /* creates a summary report
  952:  * Arguments: the filename
  953:  */
  954: int capaCreateSummary (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
  955: {    
  956:   int          section = atoi(Tcl_GetVar2(interp,"gSummary","section",TCL_GLOBAL_ONLY)), 
  957:     set = atoi(Tcl_GetVar2(interp,"gSummary","set",TCL_GLOBAL_ONLY)); 
  958:   int          studentCount,currentStudent;
  959:   int          setScores, termScores, validScores, termValids;
  960:   int          setIndex, maxSet=0;
  961:   int          whatSection;
  962:   char         fmt[64];
  963:   char         grades[4], sectionChar[4], *answersPtr, buf[BUFFER_SIZE], *who,*which,*sortOne,*sortTwo;
  964:   T_student   *studentPtr, *currentStudentPtr;
  965:   FILE        *outputFile;
  966: 
  967:   who=Tcl_GetVar2(interp,"gSummary","who",TCL_GLOBAL_ONLY);
  968:   which=Tcl_GetVar2(interp,"gSummary","which",TCL_GLOBAL_ONLY);
  969:   sortOne=Tcl_GetVar2(interp,"gSummary","first",TCL_GLOBAL_ONLY);
  970:   sortTwo=Tcl_GetVar2(interp,"gSummary","second",TCL_GLOBAL_ONLY);
  971:   maxSet=howManySetDBFile();
  972:   if ( ( ( strcmp(which,"upto") == 0 ) 
  973:        &&
  974:        ( ( set <= 0 ) 
  975: 	|| 
  976: 	( set >= NUM_SET_LIMIT ) ) ) 
  977:       ||
  978:        ( set > maxSet ) )
  979:     {
  980:       sprintf(buf,"displayError \"The set number (%d) doesn't exist.\"",set);
  981:       Tcl_Eval(interp,buf);
  982:       Tcl_ResetResult(interp);
  983:       Tcl_AppendResult(interp,"Error",NULL);
  984:       return TCL_ERROR;
  985:     }
  986:   outputFile=fopen(argv[1],"w");
  987:   if ( strcmp(who,"all") == 0 ) 
  988:       whatSection = GET_ALL_SECTIONS;
  989:   else 
  990:       whatSection = section;
  991:   studentCount = capa_get_section(&studentPtr, whatSection);
  992: 
  993:   if (Tcl_Eval(interp,"updateStatusMessage \"Creating primary sort key\"") != TCL_OK)
  994:     {
  995:       free_students(studentPtr);
  996:       fclose(outputFile);
  997:       return TCL_ERROR;
  998:     }
  999: 
 1000:   if( studentCount > 0 ) 
 1001:     {
 1002:       switch (sortOne[1]) 
 1003: 	{
 1004: 	case 'a': /*BY_NAME*/   
 1005: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1006: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)
 1007: 	    {
 1008: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1009: 	      Tcl_Eval(interp,buf);
 1010: 	      sprintf(currentStudentPtr->s_key,"%s",currentStudentPtr->s_nm);
 1011: 	    }
 1012: 	  break;
 1013: 	case 'u': /*BY_NUMBER*/  
 1014: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1015: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)  
 1016: 	    {
 1017: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1018: 	      Tcl_Eval(interp,buf);
 1019: 	      sprintf(currentStudentPtr->s_key,"%s",currentStudentPtr->s_sn);
 1020: 	    }
 1021: 	  break;
 1022: 	case 'e': /*BY_SECTION*/ 
 1023: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1024: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)  
 1025: 	    {
 1026: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1027: 	      Tcl_Eval(interp,buf);
 1028: 	      sprintf(currentStudentPtr->s_key,"%03d",currentStudentPtr->s_sec);
 1029: 	    }
 1030: 	  break;
 1031: 	case 'r': /*BY_GRADE*/
 1032: 	  if(strcmp(which,"specific") == 0 ) 
 1033: 	    {
 1034: 	      for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1035: 		  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
 1036: 		{
 1037: 		  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1038: 		  Tcl_Eval(interp,buf);
 1039: 		  if( (setScores = capa_get_score(currentStudentPtr->s_sn,set,
 1040: 						  &validScores,&answersPtr)) == -2 ) 
 1041: 		    break;
 1042: 		  if( setScores < 0 ) 
 1043: 		    sprintf(currentStudentPtr->s_key,"-");
 1044:                   else 
 1045: 		    sprintf(currentStudentPtr->s_key,"%03d",setScores);
 1046: 		  capa_mfree(answersPtr);
 1047: 		} 
 1048: 	    } 
 1049:           else 
 1050: 	    {
 1051: 	      for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1052: 		  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
 1053: 		{
 1054: 		  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1055: 		  Tcl_Eval(interp,buf);
 1056: 		  for( termScores = 0, termValids = 0, setIndex = 1; 
 1057: 		       setIndex <= set; setIndex++) 
 1058: 		    {
 1059: 		      if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex,
 1060: 						      &validScores,&answersPtr)) >= 0 ) 
 1061: 			  termScores += setScores;
 1062: 		      capa_mfree(answersPtr);
 1063: 		      termValids += validScores; 
 1064: 		    }
 1065: 		  sprintf(currentStudentPtr->s_key,"%03d",termScores);
 1066: 		}
 1067: 	    }
 1068: 	  break;
 1069: 	}
 1070:       if (Tcl_Eval(interp,"updateStatusMessage \"Creating secondary sort key\"") != TCL_OK)
 1071: 	{
 1072: 	  free_students(studentPtr);
 1073: 	  fclose(outputFile);
 1074: 	  return TCL_ERROR;
 1075: 	}
 1076:       switch (sortTwo[1]) 
 1077: 	{
 1078: 	case 'a':/*BY_NAME*/    
 1079: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1080: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)  
 1081: 	    {
 1082: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1083: 	      Tcl_Eval(interp,buf);
 1084: 	      strcat(currentStudentPtr->s_key,currentStudentPtr->s_nm);
 1085: 	    }
 1086: 	  break;
 1087: 	case 'u':/*BY_NUMBER*/  
 1088: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1089: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)  
 1090: 	    {
 1091: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1092: 	      Tcl_Eval(interp,buf);
 1093: 	      strcat(currentStudentPtr->s_key,currentStudentPtr->s_sn);
 1094: 	    }
 1095: 	  break;
 1096: 	case 'e':/*BY_SECTION*/ 
 1097: 	  for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1098: 	      currentStudentPtr=currentStudentPtr->s_next,currentStudent++)  
 1099: 	    {
 1100: 	      sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1101: 	      Tcl_Eval(interp,buf);
 1102: 	      sprintf(sectionChar,"%03d",currentStudentPtr->s_sec); 
 1103: 	      strcat(currentStudentPtr->s_key,sectionChar);
 1104: 	    }
 1105: 	  break;
 1106: 	case 'r':/*BY_GRADE*/
 1107: 	  if(strcmp(which,"specific") == 0 ) 
 1108: 	    {
 1109: 	      for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1110: 		  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
 1111: 		{
 1112: 		  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1113: 		  Tcl_Eval(interp,buf);
 1114: 		  if( (setScores = capa_get_score(currentStudentPtr->s_sn,set,&validScores,
 1115: 						  &answersPtr) ) == -2 ) 
 1116: 		    break;
 1117: 		  if( setScores < 0 ) 
 1118: 		    strcat(currentStudentPtr->s_key,"-");
 1119:                   else 
 1120: 		   {
 1121: 		     sprintf(grades,"%03d",setScores);
 1122: 		     strcat(currentStudentPtr->s_key,grades);
 1123: 		   }
 1124: 		   capa_mfree(answersPtr);
 1125: 		} 
 1126: 	    } 
 1127:          else 
 1128: 	   {
 1129: 	     for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1130: 		 currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
 1131: 	       {
 1132: 		 sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1133: 		 Tcl_Eval(interp,buf);
 1134: 		 for( termScores = 0, termValids = 0, setIndex = 1; 
 1135: 		      setIndex <= set; setIndex++) 
 1136: 		   {
 1137: 		     if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex,
 1138: 						     &validScores,&answersPtr) ) >= 0 ) 
 1139: 		       termScores += setScores;
 1140: 		     capa_mfree(answersPtr);
 1141: 		     termValids += validScores; 
 1142: 		   }
 1143: 		 sprintf(grades,"%03d",termScores);
 1144: 		 strcat(currentStudentPtr->s_key,grades);
 1145: 	       }
 1146: 	   }
 1147: 	   break;
 1148: 	}
 1149:       if (Tcl_Eval(interp,"updateStatusMessage \"Sorting\"") != TCL_OK)
 1150: 	{
 1151: 	  free_students(studentPtr);
 1152: 	  fclose(outputFile);
 1153: 	  return TCL_ERROR;
 1154: 	}
 1155:       msort_main(&studentPtr);
 1156:       Tcl_ResetResult(interp);
 1157: 
 1158:       sprintf(fmt,"%%-%ds\t%%-%ds %%2d\t", MAX_NAME_CHAR,MAX_STUDENT_NUMBER);
 1159:       if (Tcl_Eval(interp,"updateStatusMessage \"Creating Report\"") != TCL_OK)
 1160: 	{
 1161: 	  free_students(studentPtr);
 1162: 	  fclose(outputFile);
 1163: 	  return TCL_ERROR;
 1164: 	}
 1165:       for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr;
 1166: 	  currentStudentPtr=currentStudentPtr->s_next,currentStudent++) 
 1167: 	{
 1168: 	  sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount);
 1169: 	  Tcl_Eval(interp,buf);
 1170: 	  fprintf(outputFile,fmt,currentStudentPtr->s_nm,currentStudentPtr->s_sn,
 1171: 		  currentStudentPtr->s_sec);
 1172: 	  if( strcmp(which,"specific") == 0) 
 1173: 	    {
 1174: 	      setScores = 0; validScores = 0;
 1175: 	      if( (setScores = 
 1176: 		   capa_get_score(currentStudentPtr->s_sn,set,&validScores,&answersPtr) ) == -2 ) 
 1177: 		  break;
 1178: 	      if( setScores < 0 ) 
 1179: 		{
 1180: 		  fprintf(outputFile, "  -\t%3d\n", validScores);
 1181: 		} 
 1182:               else 
 1183: 		{
 1184: 		  fprintf(outputFile, "%3d\t%3d\n",setScores, validScores);
 1185: 		}
 1186: 		capa_mfree(answersPtr);
 1187: 	    } 
 1188:          else 
 1189: 	   {
 1190: 	     for( setScores=0, validScores=0, termScores = 0, termValids = 0, setIndex = 1; 
 1191: 		  setIndex <= set; setIndex++) 
 1192: 	       {
 1193: 		 if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex,
 1194: 						 &validScores,&answersPtr) ) >= 0 ) 
 1195: 		   termScores += setScores;
 1196: 		 capa_mfree(answersPtr);
 1197: 		 termValids += validScores;
 1198: 		 if( setScores >= 0 ) 
 1199: 		   {
 1200: 		     fprintf(outputFile, "%3d ",setScores);
 1201: 		   } 
 1202:                  else 
 1203: 		   {
 1204: 		     fprintf(outputFile, "  - ");
 1205: 		   }
 1206: 	       }
 1207: 	     fprintf(outputFile, "\t %3d\t%3d\n",termScores,termValids);
 1208: 	   }
 1209: 	}
 1210:       free_students(studentPtr);
 1211:     }
 1212:   fclose(outputFile);
 1213:   return TCL_OK;
 1214: }
 1215: 
 1216: /* set the gAnswer score to what ever the user entered
 1217:  * Arguments: problemNumber
 1218:  */
 1219: int capaSetHandGrade (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
 1220: {
 1221:   int problemNumber=atoi(argv[1]),handGrade,maxGrade;
 1222:   char *handGradeChar,buf[BUFFER_SIZE];
 1223: 
 1224:   handGradeChar=Tcl_GetVar(interp,"gNewHandGrade",TCL_GLOBAL_ONLY);
 1225:   sprintf(buf,"max%d",problemNumber);
 1226:   maxGrade=atoi(Tcl_GetVar2(interp,"gAnswer",buf,TCL_GLOBAL_ONLY));
 1227: 
 1228:   if (isdigit(handGradeChar[0])) {
 1229:     handGrade=atoi(handGradeChar);
 1230:     if (handGrade > maxGrade) {
 1231:       sprintf(buf,"displayError \"Invalid response, you must enter a number between 0 and %d, or an E to excuse the problem.\"",maxGrade);
 1232:       if (Tcl_Eval(interp,buf)!=TCL_OK) {
 1233: 	return TCL_ERROR;
 1234:       }
 1235:     } else {
 1236:       sprintf(buf,"%d",handGrade);
 1237:       Tcl_SetVar2(interp,"gAnswer",argv[1],buf,TCL_GLOBAL_ONLY);
 1238:     }
 1239:   } else {
 1240:     if (handGradeChar[0]=='E') {
 1241:       Tcl_SetVar2(interp,"gAnswer",argv[1],"E",TCL_GLOBAL_ONLY);
 1242:     } else {
 1243:       sprintf(buf,"displayError \"Invalid response, you must enter a number between 0 and %d, or an E to excuse the problem.\"",maxGrade);
 1244:       if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR;
 1245: 	    
 1246:     }
 1247:   }
 1248:   Tcl_ResetResult(interp);
 1249:   return TCL_OK;
 1250: }
 1251: 
 1252: /* save gAnswer to the set.db file
 1253:  * Arguments: setNum, questNum, stuId, score 
 1254:  */
 1255: int capaSetScore (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[])
 1256: {
 1257:   T_entry entry;
 1258:   int score,i,result,question,numQuest,set;
 1259:   char buf[BUFFER_SIZE],*gAnswer,*stuId;
 1260:   T_header header;
 1261: 
 1262:   if (argc != 5) 
 1263:     {
 1264:       Tcl_ResetResult(interp);
 1265:       Tcl_AppendResult(interp,"Incorrect number of arguments to save gAnswer",NULL);
 1266:       return TCL_ERROR;
 1267:     }
 1268: 
 1269:   set=atoi(argv[1]);
 1270:   question=atoi(argv[2]);
 1271:   stuId=argv[3];
 1272:   score=atoi(argv[4]);
 1273: 
 1274:   result=capa_get_header(&header,set);
 1275: 
 1276:   numQuest=atoi(header.num_questions);
 1277:   result = capa_get_entry(&entry,stuId,set);
 1278: 
 1279:   entry.answers=capa_malloc(numQuest+1,1);
 1280:   entry.tries=capa_malloc(3*numQuest+1,1);
 1281: 
 1282:   for(i=0;i<numQuest;i++) {
 1283:     if ( i==(question-1) ) {
 1284:       entry.answers[i]=score+'0';
 1285:     } else {
 1286:       entry.answers[i]='-';
 1287:     }
 1288:     entry.tries[i*3]='-';entry.tries[i*3+1]='1';
 1289:     if (i<numQuest-1) entry.tries[i*3+2]=',';
 1290:   }
 1291: 
 1292:   entry.answers[numQuest]='\0';
 1293:   entry.tries[(numQuest)*3]='\0';
 1294:   sprintf(entry.student_number,stuId);
 1295:   entry.e_probs=numQuest;
 1296:   result = capa_change_entry(&entry,stuId,set);
 1297: 
 1298:   if (result == -1) {
 1299:     Tcl_ResetResult(interp);
 1300:     Tcl_AppendResult(interp,"capa_change_entry returned an error.",NULL);
 1301:     return TCL_ERROR;
 1302:   }
 1303: 
 1304:   Tcl_ResetResult(interp);
 1305:   return TCL_OK;
 1306: }

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