Annotation of capa/capa51/pProj/qzparse.c, revision 1.5
1.5 ! albertel 1: /* main program to convert .qz files
! 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:
1.1 albertel 19: /* ======================================================================== */
20: /* Feb. 10 1997 Isaac Tsai */
21: /* ======================================================================== */
22:
23: #ifdef NeXT
24: #include <stdlib.h>
25: #include <sys/types.h>
26: #include <sys/stat.h>
27: #include <bsd/curses.h>
28: #else
29: #include <curses.h>
30: #include <malloc.h>
31: double atof();
32: #endif
33:
34: #include <stdio.h>
35: #include <ctype.h>
36: #include <sys/types.h>
37: #include <sys/stat.h>
38: #include <signal.h>
39: #include <time.h>
40: #include <math.h>
41: #include <string.h>
42:
43:
44: #define YES 1
45:
46: #include "capaParser.h"
47: #include "capaCommon.h"
48: #include "ranlib.h"
49:
1.3 albertel 50: #define Q_ONLY 1
51: #define A_ONLY 2
52: #define QA_BOTH 3
53: #define F_CLASS 1
54: #define F_SECTIONS 2
55: #define F_STUDENT 3
56: #define F_ALPHA 4
57:
1.1 albertel 58: char *progname;
59:
60: void free_header(T_header* header)
61: {
62: capa_mfree(header->weight);
63: capa_mfree(header->partial_credit);
64: }
65:
66: void setdb_error(int set)
67: {
68: fprintf(stderr,"Set #%d has not had it's DB Header set. Please run Quizzer and set the DB Header.\n",set);
69: exit(-1);
70: }
71:
72: void
73: print_header(int mode,FILE *o_fp,int sec,int set,char *stu_nam,char *stu_num)
74: {
75: extern char *StartText_p;
76: int capaid = capa_PIN(stu_num,set,0);
77:
78: if( StartText_p != NULL ) {
79: fprintf(o_fp, "%s", StartText_p);
80: }
81:
1.2 albertel 82: switch(mode) {
83: case TeX_MODE:
84: if (StartText_p == NULL ) {
85: fprintf(o_fp, "Section %d {\\Large %s}\\hspace*{1in}",sec,stu_nam);
86: fprintf(o_fp, "{\\large %s}, CAPAID: %d, set %d",stu_num, capaid, set);
87: }
88: fprintf(o_fp, "\n\\begin{enumerate}\n");
89: break;
90: case ASCII_MODE:
91: fprintf(o_fp, "Section %d %s ", sec,stu_nam);
92: fprintf(o_fp, "%s, CAPAID: %d set %d\n\n",stu_num, capaid, set);
93: break;
94: case HTML_MODE:
95: fprintf(o_fp, "<H2>Section %d %s, ", sec,stu_nam);
96: fprintf(o_fp, "%s, CAPAID:%d set %d</H2>\n", stu_num,capaid,set);
97: fprintf(o_fp, "<OL>\n");
98: break;
99: }
1.1 albertel 100: }
101:
102: void
103: print_begin_item(int mode,FILE *o_fp,int q_idx)
104: {
105:
106: switch(mode) {
107: case TeX_MODE:
108: fprintf(o_fp, "\\item ");
109: break;
110: case ASCII_MODE:
111: fprintf(o_fp, "%d) ", q_idx);
112: break;
113: case HTML_MODE:
114: fprintf(o_fp, "<LI> ");
115: break;
116: }
117: }
118:
119:
120: void
121: unit_toHTML(char *u_str, char *r)
122: {
123: int i;
124: char *ch;
125:
126:
127: while(isspace(*ch)) ch++;
128: while( isalnum(*ch) ) {
129: r[i++] = *ch; ch++;
130: }
131: if( *ch == '^' ) {
132: r[i++] = '<'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>';
133: ch++; while(isspace(*ch)) ch++;
134: while( isalnum(*ch) ) {
135: r[i++] = *ch; ch++;
136: }
137: r[i++] = '<'; r[i++]='/'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>';
138: } else {
139: r[i++] = *ch; ch++;
140: }
141:
142:
143: }
144:
145: void
146: print_footer(int mode,FILE *o_fp)
147: {
148: extern char *EndText_p;
149:
150: switch(mode) {
151: case TeX_MODE:
152: fprintf(o_fp, "\n\\end{enumerate}\n");
153: break;
154: case ASCII_MODE:
155: fprintf(o_fp, "\n");
156: break;
157: case HTML_MODE:
158: fprintf(o_fp, "</OL>\n");
159: break;
160: }
161: if( EndText_p != NULL ) {
162: fprintf(o_fp, "%s", EndText_p);
163: }
164: }
165:
1.3 albertel 166: void output_problems(Problem_t* first_prob,int outputFlag,int q_cnt,FILE* dfp,
167: T_student* a_student,int setIdx)
168: {
169: extern int Parsemode_f;
170: extern char *EndText_p;
171: extern char *StartText_p;
172:
173: Problem_t *p;
174: int q_idx;
175: char* ans_str;
176:
177: p = first_prob;
178: switch(outputFlag) {
179: case Q_ONLY:
180: if( StartText_p != NULL) {
181: fprintf(dfp, "%s", StartText_p); fflush(dfp);
182: }
183: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
184: fprintf(dfp, "%s", p->question); p = p->next;
185: }
186: if( EndText_p != NULL) {
187: fprintf(dfp, "%s", EndText_p); fflush(dfp);
188: }
189: break;
190: case A_ONLY:
191: print_header(Parsemode_f, dfp,a_student->s_sec,setIdx,a_student->s_nm,
192: a_student->s_sn);
193: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
194: print_begin_item(Parsemode_f,dfp,q_idx+1);
195: ans_str = answers_string(Parsemode_f,p);
196: fprintf(dfp, "%s",ans_str); fflush(dfp);
197: capa_mfree((char *)ans_str);
198: p = p->next;
199: }
200: print_footer(Parsemode_f, dfp);
201: break;
202: case QA_BOTH:
203: if( StartText_p != NULL ) {
204: fprintf(dfp, "%s", StartText_p);
205: }
206: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
207: fprintf(dfp, "%s", p->question); fflush(dfp);
208: ans_str = answers_string(Parsemode_f,p);
209: fprintf(dfp, "%s",ans_str); fflush(dfp);
210: capa_mfree((char *)ans_str);
211: p = p->next;
212: }
213: if( EndText_p != NULL ) {
214: fprintf(dfp, "%s", EndText_p);
215: }
216: break;
217: }
218: }
219:
1.1 albertel 220: /* ============================================================== */
221: /* qz --> tex -Tq */
222: /* qz --> html -Ha */
223: /* qz --> ascii -Ab */
224: /* question only q */
225: /* answer only a */
226: /* both b */
227: /* for entire class -C */
228: /* for a range of sections -Sec 2:6 */
229: /* for a section -Sec 2 */
230: /* for a student -Stu 12345678 */
231: /* output a set -Set 2 */
232: /* output a range of sets -Set 1:6 */
233: /* output blocksize -b 30 */
234: /* ============================================================== */
235:
236: void usage()
237: {
238: printf("USAGE: %s [ -[T|H|A][a|b] ] [-Sec [n|n:m] | -Stu sn [-o filename] ]\n",progname);
239: printf(" [ -Set [n|n:m] ] [-c path_to_class] [-d outputdirectory]\n");
240: printf(" Example 1: %s -Tb -sec 2:3 -set 2:5\n", progname);
241: printf(" will generate tex files with both questions and answers\n");
242: printf(" for sections 2 to 3, sets 2 to 5\n");
243: printf(" Example 2: %s -Ha -stu A12345678 -set 3\n", progname);
244: printf(" will generate html files with answer only \n");
245: printf(" for student A12345678 set 3\n");
246: printf(" -T = tex mode\n");
247: printf(" -H = html mode\n");
248: printf(" -A = ascii mode\n");
249: printf(" = default question only\n");
250: printf(" a = answer only\n");
251: printf(" b = both question and answer\n");
252: printf(" -nopagebreak = don't put a \\clearpage between assignments\n");
253: printf(" -Sec 3 = for section 3\n");
254: printf(" -Sec 3:7 = from section 3 to section 7\n");
255: printf(" -Stu A12345678 = for a specified student\n");
256: printf(" -Set 1 = output set 1\n");
257: printf(" -Set 3:4 = output from set 3 to set 4\n");
258: printf(" -c class_path\n");
259: printf(" -o output_filename_with_absolute_path (only for a student)\n");
260: printf(" -d directory_to_create_files_in (default is class_path/TeX)\n");
261: printf("-------This is version %s @ %s\n",CAPA_VER,COMPILE_DATE);
262: printf("------------------------------------------------------\n");
263: }
264:
265: /* filter out the number to be [1:999] */
266: int scan_num(char *num_str,int *first, int *second) {
267: char tmp_str[SMALL_LINE_BUFFER], *ch;
268: int ii=0, a_num, b_num, result=0;
269:
270: ch = num_str;
271: tmp_str[ii] = 0;
272: while( isspace(*ch) ) ch++;
273: while(isdigit(*ch)) { tmp_str[ii++] = *ch; ch++; }
274: tmp_str[ii] = 0;
275: sscanf(tmp_str,"%d",&a_num);
276: if( a_num < 0 || a_num > 999 ) a_num = 1;
277: *first = a_num;
278: result = 1;
279: while( isspace(*ch) ) ch++;
280: if( *ch == ':' ) {
281: ch++;
282: while( isspace(*ch) ) ch++;
283: ii=0; tmp_str[ii] = 0;
284: while( isdigit(*ch) ) { tmp_str[ii++] = *ch; ch++; }
285: tmp_str[ii] = 0;
286: sscanf(tmp_str,"%d",&b_num);
287: if( b_num < 0 || b_num > 999 ) b_num = 1;
288: if( a_num > b_num ) b_num = a_num;
289: *second = b_num;
290: result = 2;
291: }
292: return (result);
293: }
294:
1.3 albertel 295: FILE* start_set(int directory_specified,char* out_directory,int file_specified,
296: char *out_filename,char* filestart,char* filename)
297: {
298: extern int Parsemode_f;
299:
300: char cmd[MAX_BUFFER_SIZE];
301: FILE* dfp;
302:
303: if (file_specified == 0) {
304: if (directory_specified == 0 ) {
305: switch( Parsemode_f ) {
306: case TeX_MODE:
307: sprintf(filename,"TeX/%s.tex",filestart);
308: break;
309: case ASCII_MODE:
310: sprintf(filename,"ASCII/%s.ascii",filestart);
311: break;
312: case HTML_MODE:
313: sprintf(filename,"HTML/%s.text",filestart);
314: break;
315: }
316: } else {
317: switch( Parsemode_f ) {
318: case TeX_MODE:
319: sprintf(filename,"%s/%s.tex",out_directory,filestart);
320: break;
321: case ASCII_MODE:
322: sprintf(filename,"%s/%s.ascii",out_directory,filestart);
323: break;
324: case HTML_MODE:
325: sprintf(filename,"%s/%s.text", out_directory,filestart);
326: break;
327: }
328: }
329: } else {
330: if (directory_specified == 0 ) {
331: sprintf(filename,"%s",out_filename);
332: } else {
333: sprintf(filename,"%s/%s",out_directory,out_filename);
334: }
335: }
336: switch ( Parsemode_f ) {
337: case TeX_MODE: sprintf(cmd, "cp TeXheader %s\n",filename); system(cmd); break;
338: default: sprintf(cmd,"rm %s\n",filename);system(cmd); break;
339: }
340:
341: if((dfp=fopen(filename,"a"))==NULL) { printf("File error\n"); exit(-1); }
342: return dfp;
343: }
344:
345: void end_set(FILE*dfp,char* filename)
346: {
347: extern int Parsemode_f;
348: char cmd[MAX_BUFFER_SIZE];
349: fflush(dfp);
350: fclose(dfp);
351: if(Parsemode_f == TeX_MODE) {
352: sprintf(cmd, "cat TeXfooter >> %s\n", filename);
353: system(cmd);
354: }
355: }
356:
357: void end_page(FILE*dfp,int pagebreak)
358: {
359: extern int Parsemode_f;
360: if( Parsemode_f == TeX_MODE && pagebreak ) {
361: fprintf(dfp, "\\clearpage\n\\setcounter{page}{1}\n"); fflush(dfp);
362: } else {
363: printf("\n");
364: }
365: }
366:
1.1 albertel 367: int main (int argc, char **argv)
368: {
369: extern int Parsemode_f;
370: extern char *EndText_p;
371: extern char *StartText_p;
372: extern char *ErrorMsg_p;
373: extern int ErrorMsg_count;
374:
375: Problem_t *first_prob,*p;
376: T_student *students_p,*s_p, a_student;
377: int num_students, q_cnt, result, inputNotOK = 1,
378: ii, sectionIdx, setIdx = 1, q_idx, outputFlag = 0;
1.3 albertel 379: char filename[FILE_NAME_LENGTH], path[FILE_NAME_LENGTH],
380: filestart[FILE_NAME_LENGTH];
1.1 albertel 381: FILE *dfp;
382: int tmp_num, first_stu, file_specified, directory_specified;
383: int ForWhat = F_SECTIONS, pagebreak=1,
384: StartSec = 1, EndSec = 1, StartSet = 1, EndSet = 1;
385: char StuNum[MAX_STUDENT_NUMBER+1];
386: char out_filename[FILE_NAME_LENGTH],out_directory[FILE_NAME_LENGTH];
387: char cmd[SMALL_LINE_BUFFER], *ans_str;
388:
389: /* qz --> tex -T */
390: /* qz --> html -Ha */
391: /* qz --> ascii -Ab */
392: /* answer only a */
393: /* both b */
394: /* for entire class -C */
395: /* for a range of sections -Sec 2:6 */
396: /* for a section -Sec 2 */
397: /* for a student -Stu 12345678 */
398: /* output a set -Set 2 */
399: /* output a range of sets -Set 1:6 */
400:
401: /* default */
402: Parsemode_f = TeX_MODE; ForWhat = F_SECTIONS; outputFlag=Q_ONLY;
403: file_specified=0;
404: out_filename[0]='\0';
405: directory_specified=0;
406: out_directory[0]='\0';
407: for( progname = *argv++; --argc; argv++) {
408: if ( argv[0][0] == '-' ) {
409: switch(argv[0][1]) {
410: case 'T': Parsemode_f = TeX_MODE;
411: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
412: break;
413: case 'H': Parsemode_f = HTML_MODE;
414: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
415: break;
416: case 'A': Parsemode_f = ASCII_MODE;
417: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
418: break;
419: case 'S':
420: case 's': if( strncasecmp(argv[0],"-sec",4) == 0 ) {
421: tmp_num = scan_num(argv[1],&StartSec,&EndSec);
422: if( tmp_num == 1 ) { EndSec = StartSec; }
423: ForWhat = F_SECTIONS;
424: } else if( strncasecmp(argv[0],"-stu",4) == 0 ) {
425: for(ii=0;ii<MAX_STUDENT_NUMBER;ii++) {
426: StuNum[ii] = argv[1][ii];
427: }
428: StuNum[ii]=0;
429: ForWhat = F_STUDENT;
430: } else if( strncasecmp(argv[0],"-set",4) == 0 ) {
431: tmp_num = scan_num(argv[1],&StartSet,&EndSet);
432: if( tmp_num == 1 ) { EndSet = StartSet; }
433: } else {
434: usage();
435: }
436: break;
437: case 'c': strcpy(path, argv[1]);
438: if(capa_access(path, F_OK) == -1) {
439: inputNotOK = 1;
440: } else {
441: inputNotOK = 0;
442: }
443: break;
444: case 'o':
445: if (argc == 1 || argv[1][0] == '-') {
446: usage(); return 0;
447: } else {
448: strcpy(out_filename, argv[1]); file_specified=1; break;
449: }
450: case 'd':
451: if (argc == 1 || argv[1][0] == '-') {
452: usage(); return 0; break;
453: } else {
454: strcpy(out_directory, argv[1]); directory_specified=1; break;
455: }
456: case 'n':
457: pagebreak=0;break;
458: case 'u': case 'h': default: usage(); return(0); break;
459: }
460: }
461: }
462: printf(" %s running in %s mode, %s for %s, ", progname,
463: (Parsemode_f == TeX_MODE ? "TeX" : (Parsemode_f == ASCII_MODE ? "ASCII" : "HTML")),
464: (outputFlag==A_ONLY ? "answer only" : (outputFlag==QA_BOTH? "question and answer" : "question only")),
465: (ForWhat == F_STUDENT ? "a student" : "section" ) );
466: if( ForWhat == F_STUDENT ) {
467: printf(" for student %s,",StuNum);
468: } else {
469: if(StartSec==EndSec) {
470: printf(" for section %d,", StartSec);
471: }
472: else {
473: printf(" from section %d to %d,",StartSec, EndSec);
474: }
475: }
476: if(StartSet==EndSet) { printf(" set %d\n",StartSet); } else { printf(" from set %d to %d\n", StartSet, EndSet); }
477:
478: while ( inputNotOK ) {
479: puts("Enter the ABSOLUTE path of class");
480: scanf("%s", path);
481: if( capa_access(path, F_OK) == -1 ) {
482: } else {
483: sprintf(filename,"%s/classl",path);
484: if( capa_access(filename, F_OK) == -1 ) {
485: puts("There isn't a classl file in this CLASS directory\nPlease Specify another class");
486: } else {
487: inputNotOK = 0;
488: }
489: }
490: }
491:
492: if( (ForWhat == F_STUDENT) && strlen(StuNum) == 0 ) {
493: inputNotOK = 1;
494: while ( inputNotOK ) {
495: puts("Enter student number"); scanf("%s", StuNum);
496: if( strlen(StuNum) == MAX_STUDENT_NUMBER ) { inputNotOK = 0; }
497: }
498: }
499: if ( file_specified == 0) {
500: if ( directory_specified == 0) {
501: switch( Parsemode_f ) {
502: case TeX_MODE: sprintf(filename,"%s/TeX",path); break;
503: case ASCII_MODE: sprintf(filename,"%s/ASCII",path); break;
504: case HTML_MODE: sprintf(filename,"%s/HTML",path); break;
505: default: sprintf(filename,"%s/TeX",path); Parsemode_f = TeX_MODE; break;
506: }
507: } else {
508: sprintf(filename,"%s",out_directory);
509: }
510: if( capa_access(filename, F_OK) == -1 ) {
511: if ( mkdir(filename, S_IREAD | S_IWRITE | S_IEXEC ) == -1 ) {
512: printf("Unable to write to %s\n",filename);
513: printf("Please check this directory and run %s again.\n",progname);
514: return(-1);
515: }
516: }
517:
518: } else {
519: if ( directory_specified == 0) {
520: } else {
521: sprintf(filename,"%s",out_directory);
522: }
523: }
524: chdir(path);
525:
526: if ( ForWhat == F_SECTIONS ) {
527: T_dates* dates;
528: T_header header;
529: for(ii=StartSet;ii<=EndSet;ii++) {
1.3 albertel 530: if (capa_get_header(&header,ii)<0) setdb_error(ii);
531: free_header(&header);
532: if (capa_get_all_dates(ii,&dates)<0) setdb_error(ii);
533: free_dates(dates);
1.1 albertel 534: }
535: }
536:
1.3 albertel 537: switch (ForWhat) {
538: case F_STUDENT:
539: result = capa_get_student(StuNum, &a_student);
540: if ( result == 0 ) {
541: fprintf(stderr,"Unable to find student %s in %s/classl",StuNum,path);
542: exit(-1);
543: } else {
544: if (result == -1 ) {
545: fprintf(stderr,"Unable to read %s/classl",path);
546: exit(-1);
547: }
1.1 albertel 548: }
1.3 albertel 549: dfp=start_set(directory_specified,out_directory,file_specified,out_filename,
550: StuNum,filename);
551: for(setIdx=StartSet; setIdx <= EndSet; setIdx++) {
552: result = capa_parse(setIdx, &first_prob, StuNum, &q_cnt, NULL);
553: if ( result != 0 ) {
554: output_problems(first_prob,outputFlag,q_cnt,dfp,&a_student,setIdx);
555: free_problems(first_prob);
556: }
557: if( setIdx < EndSet ) { end_page(dfp,pagebreak); }
558: if( ErrorMsg_count > 0 ) { printf("%s",ErrorMsg_p); }
1.1 albertel 559: }
1.4 albertel 560: end_set(dfp,filename);
1.3 albertel 561: printf("\n DONE Student %s\n",StuNum);
562: break;
563: case F_SECTIONS:
564: for(sectionIdx = StartSec; sectionIdx <= EndSec; sectionIdx++ ) {
565: num_students = capa_sorted_section(&students_p, sectionIdx);
566: if( num_students > 0 ) {
567: printf("Section %2d: %d students\n",sectionIdx,num_students);
568: for(setIdx=StartSet; setIdx <= EndSet; setIdx++) {
569: sprintf(filestart,"section%d-set%d",sectionIdx,setIdx);
570: dfp=start_set(directory_specified,out_directory,file_specified,
571: out_filename,filestart,filename);
572: for(s_p = students_p,first_stu=1; s_p ; s_p = s_p->s_next ) {
573: s_p->s_sn[MAX_STUDENT_NUMBER]=0;
574: printf(" Student: %s%s set %d\n",s_p->s_nm,s_p->s_sn,setIdx);
575: result = capa_parse(setIdx, &first_prob, s_p->s_sn, &q_cnt, NULL);
576: if ( result != 0 ) {
577: output_problems(first_prob,outputFlag,q_cnt,dfp,s_p,setIdx);
578: free_problems(first_prob);
579: if( s_p->s_next != NULL ) { end_page(dfp,pagebreak); }
580: }
581: }
582: end_set(dfp,filename);
583: printf("\n DONE set%2d\n",setIdx);
584: }
585: }
586: printf("\n DONE section%2d\n",sectionIdx);
1.1 albertel 587: }
1.3 albertel 588: free_students(students_p);
589: break;
590: case F_ALPHA:
591: break;
1.1 albertel 592: }
593: printf("ALL DONE\n");
594: return (0);
595: }
596:
597:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>