/* main program to convert .qz files Copyright (C) 1992-2000 Michigan State University The CAPA system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The CAPA system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the CAPA system; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, you have permission to link this program with the TtH/TtM library and distribute executables, as long as you follow the requirements of the GNU GPL in regard to all of the software in the executable aside from TtH/TtM. */ /* ======================================================================== */ /* Feb. 10 1997 Isaac Tsai */ /* ======================================================================== */ #ifdef NeXT #include #include #include #include #else #include #include double atof(); #endif #include #include #include #include #include #include #include #include #define YES 1 #include "capaParser.h" #include "capaCommon.h" #include "ranlib.h" #define Q_ONLY 1 #define A_ONLY 2 #define QA_BOTH 3 #define F_CLASS 1 #define F_SECTIONS 2 #define F_STUDENT 3 #define F_ALPHA 4 char *progname; void free_header(T_header* header) { capa_mfree(header->weight); capa_mfree(header->partial_credit); } void setdb_error(int set) { fprintf(stderr,"Set #%d has not had it's DB Header set. Please run Quizzer and set the DB Header.\n",set); exit(-1); } void print_header(int mode,FILE *o_fp,int sec,int set,char *stu_nam,char *stu_num) { extern char *StartText_p; int capaid = capa_PIN(stu_num,set,0); if( StartText_p != NULL ) { fprintf(o_fp, "%s", StartText_p); } switch(mode) { case TeX_MODE: if (StartText_p == NULL ) { fprintf(o_fp, "Section %d {\\Large %s}\\hspace*{1in}",sec,stu_nam); fprintf(o_fp, "{\\large %s}, CAPAID: %d, set %d",stu_num, capaid, set); } fprintf(o_fp, "\n\\begin{enumerate}\n"); break; case ASCII_MODE: fprintf(o_fp, "Section %d %s ", sec,stu_nam); fprintf(o_fp, "%s, CAPAID: %d set %d\n\n",stu_num, capaid, set); break; case HTML_MODE: fprintf(o_fp, "

Section %d %s, ", sec,stu_nam); fprintf(o_fp, "%s, CAPAID:%d set %d

\n", stu_num,capaid,set); fprintf(o_fp, "
    \n"); break; } } void print_begin_item(int mode,FILE *o_fp,int q_idx) { switch(mode) { case TeX_MODE: fprintf(o_fp, "\\item "); break; case ASCII_MODE: fprintf(o_fp, "%d) ", q_idx); break; case HTML_MODE: fprintf(o_fp, "
  1. "); break; } } void unit_toHTML(char *u_str, char *r) { int i; char *ch; while(isspace(*ch)) ch++; while( isalnum(*ch) ) { r[i++] = *ch; ch++; } if( *ch == '^' ) { r[i++] = '<'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>'; ch++; while(isspace(*ch)) ch++; while( isalnum(*ch) ) { r[i++] = *ch; ch++; } r[i++] = '<'; r[i++]='/'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>'; } else { r[i++] = *ch; ch++; } } void print_footer(int mode,FILE *o_fp) { extern char *EndText_p; switch(mode) { case TeX_MODE: fprintf(o_fp, "\n\\end{enumerate}\n"); break; case ASCII_MODE: fprintf(o_fp, "\n"); break; case HTML_MODE: fprintf(o_fp, "
\n"); break; } if( EndText_p != NULL ) { fprintf(o_fp, "%s", EndText_p); } } void output_problems(Problem_t* first_prob,int outputFlag,int q_cnt,FILE* dfp, T_student* a_student,int setIdx) { extern int Parsemode_f; extern char *EndText_p; extern char *StartText_p; Problem_t *p; int q_idx; char* ans_str; p = first_prob; switch(outputFlag) { case Q_ONLY: if( StartText_p != NULL) { fprintf(dfp, "%s", StartText_p); fflush(dfp); } for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) { fprintf(dfp, "%s", p->question); p = p->next; } if( EndText_p != NULL) { fprintf(dfp, "%s", EndText_p); fflush(dfp); } break; case A_ONLY: print_header(Parsemode_f, dfp,a_student->s_sec,setIdx,a_student->s_nm, a_student->s_sn); for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) { print_begin_item(Parsemode_f,dfp,q_idx+1); ans_str = answers_string(Parsemode_f,p); fprintf(dfp, "%s",ans_str); fflush(dfp); capa_mfree((char *)ans_str); p = p->next; } print_footer(Parsemode_f, dfp); break; case QA_BOTH: if( StartText_p != NULL ) { fprintf(dfp, "%s", StartText_p); } for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) { fprintf(dfp, "%s", p->question); fflush(dfp); ans_str = answers_string(Parsemode_f,p); fprintf(dfp, "%s",ans_str); fflush(dfp); capa_mfree((char *)ans_str); p = p->next; } if( EndText_p != NULL ) { fprintf(dfp, "%s", EndText_p); } break; } } /* ============================================================== */ /* qz --> tex -Tq */ /* qz --> html -Ha */ /* qz --> ascii -Ab */ /* question only q */ /* answer only a */ /* both b */ /* for entire class -C */ /* for a range of sections -Sec 2:6 */ /* for a section -Sec 2 */ /* for a student -Stu 12345678 */ /* output a set -Set 2 */ /* output a range of sets -Set 1:6 */ /* output blocksize -b 30 */ /* ============================================================== */ void usage() { printf("USAGE: %s [ -[T|H|A][a|b] ] [-Sec [n|n:m] | -Stu sn [-o filename] ]\n",progname); printf(" [ -Set [n|n:m] ] [-c path_to_class] [-d outputdirectory]\n"); printf(" Example 1: %s -Tb -sec 2:3 -set 2:5\n", progname); printf(" will generate tex files with both questions and answers\n"); printf(" for sections 2 to 3, sets 2 to 5\n"); printf(" Example 2: %s -Ha -stu A12345678 -set 3\n", progname); printf(" will generate html files with answer only \n"); printf(" for student A12345678 set 3\n"); printf(" -T = tex mode\n"); printf(" -H = html mode\n"); printf(" -A = ascii mode\n"); printf(" = default question only\n"); printf(" a = answer only\n"); printf(" b = both question and answer\n"); printf(" -nopagebreak = don't put a \\clearpage between assignments\n"); printf(" -Sec 3 = for section 3\n"); printf(" -Sec 3:7 = from section 3 to section 7\n"); printf(" -Stu A12345678 = for a specified student\n"); printf(" -Set 1 = output set 1\n"); printf(" -Set 3:4 = output from set 3 to set 4\n"); printf(" -c class_path\n"); printf(" -o output_filename_with_absolute_path (only for a student)\n"); printf(" -d directory_to_create_files_in (default is class_path/TeX)\n"); printf("-------This is version %s @ %s\n",CAPA_VER,COMPILE_DATE); printf("------------------------------------------------------\n"); printf("CAPA is released under GNU GPL v2, see COPYING for details.\n"); } /* filter out the number to be [1:999] */ int scan_num(char *num_str,int *first, int *second) { char tmp_str[SMALL_LINE_BUFFER], *ch; int ii=0, a_num, b_num, result=0; ch = num_str; tmp_str[ii] = 0; while( isspace(*ch) ) ch++; while(isdigit(*ch)) { tmp_str[ii++] = *ch; ch++; } tmp_str[ii] = 0; sscanf(tmp_str,"%d",&a_num); if( a_num < 0 || a_num > 999 ) a_num = 1; *first = a_num; result = 1; while( isspace(*ch) ) ch++; if( *ch == ':' ) { ch++; while( isspace(*ch) ) ch++; ii=0; tmp_str[ii] = 0; while( isdigit(*ch) ) { tmp_str[ii++] = *ch; ch++; } tmp_str[ii] = 0; sscanf(tmp_str,"%d",&b_num); if( b_num < 0 || b_num > 999 ) b_num = 1; if( a_num > b_num ) b_num = a_num; *second = b_num; result = 2; } return (result); } FILE* start_set(int directory_specified,char* out_directory,int file_specified, char *out_filename,char* filestart,char* filename) { extern int Parsemode_f; char cmd[MAX_BUFFER_SIZE]; FILE* dfp; if (file_specified == 0) { if (directory_specified == 0 ) { switch( Parsemode_f ) { case TeX_MODE: sprintf(filename,"TeX/%s.tex",filestart); break; case ASCII_MODE: sprintf(filename,"ASCII/%s.ascii",filestart); break; case HTML_MODE: sprintf(filename,"HTML/%s.text",filestart); break; } } else { switch( Parsemode_f ) { case TeX_MODE: sprintf(filename,"%s/%s.tex",out_directory,filestart); break; case ASCII_MODE: sprintf(filename,"%s/%s.ascii",out_directory,filestart); break; case HTML_MODE: sprintf(filename,"%s/%s.text", out_directory,filestart); break; } } } else { if (directory_specified == 0 ) { sprintf(filename,"%s",out_filename); } else { sprintf(filename,"%s/%s",out_directory,out_filename); } } switch ( Parsemode_f ) { case TeX_MODE: sprintf(cmd, "cp TeXheader %s\n",filename); system(cmd); break; default: sprintf(cmd,"rm %s\n",filename);system(cmd); break; } if((dfp=fopen(filename,"a"))==NULL) { printf("File error\n"); exit(-1); } return dfp; } void end_set(FILE*dfp,char* filename) { extern int Parsemode_f; char cmd[MAX_BUFFER_SIZE]; fflush(dfp); fclose(dfp); if(Parsemode_f == TeX_MODE) { sprintf(cmd, "cat TeXfooter >> %s\n", filename); system(cmd); } } void end_page(FILE*dfp,int pagebreak) { extern int Parsemode_f; if( Parsemode_f == TeX_MODE && pagebreak ) { fprintf(dfp, "\\clearpage\n\\setcounter{page}{1}\n"); fflush(dfp); } else { printf("\n"); } } int main (int argc, char **argv) { extern int Parsemode_f; extern char *EndText_p; extern char *StartText_p; extern char *ErrorMsg_p; extern int ErrorMsg_count; Problem_t *first_prob,*p; T_student *students_p,*s_p, a_student; int num_students, q_cnt, result, inputNotOK = 1, ii, sectionIdx, setIdx = 1, q_idx, outputFlag = 0; char filename[FILE_NAME_LENGTH], path[FILE_NAME_LENGTH], filestart[FILE_NAME_LENGTH]; FILE *dfp; int tmp_num, first_stu, file_specified, directory_specified; int ForWhat = F_SECTIONS, pagebreak=1, StartSec = 1, EndSec = 1, StartSet = 1, EndSet = 1; char StuNum[MAX_STUDENT_NUMBER+1]; char out_filename[FILE_NAME_LENGTH],out_directory[FILE_NAME_LENGTH]; char cmd[SMALL_LINE_BUFFER], *ans_str; /* qz --> tex -T */ /* qz --> html -Ha */ /* qz --> ascii -Ab */ /* answer only a */ /* both b */ /* for entire class -C */ /* for a range of sections -Sec 2:6 */ /* for a section -Sec 2 */ /* for a student -Stu 12345678 */ /* output a set -Set 2 */ /* output a range of sets -Set 1:6 */ /* default */ Parsemode_f = TeX_MODE; ForWhat = F_SECTIONS; outputFlag=Q_ONLY; file_specified=0; out_filename[0]='\0'; directory_specified=0; out_directory[0]='\0'; for( progname = *argv++; --argc; argv++) { if ( argv[0][0] == '-' ) { switch(argv[0][1]) { case 'T': Parsemode_f = TeX_MODE; outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY)); break; case 'H': Parsemode_f = HTML_MODE; outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY)); break; case 'A': Parsemode_f = ASCII_MODE; outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY)); break; case 'S': case 's': if( strncasecmp(argv[0],"-sec",4) == 0 ) { tmp_num = scan_num(argv[1],&StartSec,&EndSec); if( tmp_num == 1 ) { EndSec = StartSec; } ForWhat = F_SECTIONS; } else if( strncasecmp(argv[0],"-stu",4) == 0 ) { for(ii=0;ii 0 ) { printf("%s",ErrorMsg_p); } } end_set(dfp,filename); printf("\n DONE Student %s\n",StuNum); break; case F_SECTIONS: for(sectionIdx = StartSec; sectionIdx <= EndSec; sectionIdx++ ) { num_students = capa_sorted_section(&students_p, sectionIdx); if( num_students > 0 ) { printf("Section %2d: %d students\n",sectionIdx,num_students); for(setIdx=StartSet; setIdx <= EndSet; setIdx++) { sprintf(filestart,"section%d-set%d",sectionIdx,setIdx); dfp=start_set(directory_specified,out_directory,file_specified, out_filename,filestart,filename); for(s_p = students_p,first_stu=1; s_p ; s_p = s_p->s_next ) { s_p->s_sn[MAX_STUDENT_NUMBER]=0; printf(" Student: %s%s set %d\n",s_p->s_nm,s_p->s_sn,setIdx); result = capa_parse(setIdx, &first_prob, s_p->s_sn, &q_cnt, NULL); if ( result != 0 ) { output_problems(first_prob,outputFlag,q_cnt,dfp,s_p,setIdx); free_problems(first_prob); if( s_p->s_next != NULL ) { end_page(dfp,pagebreak); } } } end_set(dfp,filename); printf("\n DONE set%2d\n",setIdx); } } printf("\n DONE section%2d\n",sectionIdx); } free_students(students_p); break; case F_ALPHA: break; } printf("ALL DONE\n"); return (0); }