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