1: /* Copyright 1992-1997 Michigan State University, Board of Trustee */
2: /* version 4.6 */
3:
4: /* Jan 28 1997 I.T. */
5: /* July 23 1998 I.T. */
6:
7: #ifdef NeXT
8: #include <stdlib.h>
9: #include <objc/zone.h>
10: #include <mach/mach.h>
11: #else
12: #include <malloc.h>
13: double atof();
14: #endif
15:
16: #include <ctype.h>
17:
18: #ifdef TRUE
19: #undef TRUE
20: #endif
21: #ifdef FALSE
22: #undef FALSE
23: #endif
24:
25: #include <curses.h>
26:
27: #if defined(__alpha) || defined(linux)
28:
29: #ifdef LOGIN_DBUG
30:
31: #define NO_PIN
32: #define NO_DATE_CHECK
33: #define NO_DUP_CHECK
34:
35: #endif
36:
37: #include <curses.h>
38: #else
39: #if defined(__sun) || defined(hpux) || defined(AIX) || defined(IRIX)
40: #include <curses.h> /* #include <stdio.h> */
41: #include <math.h> /* MAXFLOAT */
42:
43: #else
44:
45: #include <bsd/curses.h>
46:
47: #endif
48: #endif
49:
50: #include <signal.h>
51: #include <time.h>
52: #include <math.h>
53: #include <string.h>
54: #include <unistd.h>
55: #include "capaToken.h"
56: #include "capaParser.h"
57: #include "capaCommon.h"
58:
59: FILE *dfp;
60:
61: #define TERM_SUMMARY 1
62: #define EXAM_SUMMARY 2
63: #define QUIZ_SUMMARY 3
64:
65: #define TRY_BOUND 99
66:
67:
68:
69:
70: #define TYR_SET_MENU_MACRO(xxx) { \
71: sprintf(aLine,"Total %d problems", num_questions); \
72: if(xxx) { \
73: mvaddstr(20,1,"Enter command M, A, #, T, or X."); mvaddstr(20,67,"COMMAND:"); \
74: mvaddstr(21,1,"M=go to Main Menu A=Answer T=Time RETURN=execute command"); \
75: } else { \
76: mvaddstr(20,1,"Enter command M, #, T, or X. "); mvaddstr(20,67,"COMMAND:"); \
77: mvaddstr(21,1,"M=go to Main Menu T=Time RETURN=execute command"); \
78: } \
79: mvaddstr(22,1, "#=go to problem # X=eXit CAPA"); \
80: mvaddstr(23,1,aLine); }
81:
82:
83: #define REVIEW_SET_MENU_MACRO() { \
84: sprintf(aLine,"Total %d problems", num_questions); \
85: mvaddstr(20,1,"Enter command M, #, or X."); mvaddstr(20,67,"COMMAND:"); \
86: mvaddstr(21,1,"M=go to Main Menu RETURN=execute command"); \
87: mvaddstr(22,1,"#=go to problem # X=eXit CAPA"); \
88: mvaddstr(23,1,aLine); }
89:
90: #define TYRSET_MENU( ) { \
91: mvaddstr(22,0,"Commands :M = Main Menu :7 = go to Problem 7 RETURN = Enter/Execute"); \
92: }
93:
94:
95: #define REVIEW_SET_MENU_MACRO() { \
96: sprintf(aLine,"Total %d problems", num_questions); \
97: mvaddstr(20,1,"Enter command M, #, or X."); mvaddstr(20,67,"COMMAND:"); \
98: mvaddstr(21,1,"M=go to Main Menu RETURN=execute command"); \
99: mvaddstr(22,1,"#=go to problem # X=eXit CAPA"); \
100: mvaddstr(23,1,aLine); }
101:
102:
103: #define DBUG_TSUMMARY 0
104:
105: #define CLEAR() clear(); refresh()
106: #define ADDCH(c) addch(c); refresh()
107: #define CLRTOEOL() clrtoeol(); refresh()
108: #define CR 13
109: #define LF 10
110: #define SCREEN_BUFFER_SIZE 2048
111:
112: time_t log_in_time, log_out_time;
113: char in_t[32], in_tty[32];
114: char Orig_path[FILE_NAME_LENGTH], Exam_path[FILE_NAME_LENGTH],
115: Quiz_path[FILE_NAME_LENGTH];
116: int Exam_set, Quiz_set;
117: int g_inhibit_response;
118: int g_delay; /* delay when logging out */
119: int g_max_delay; /* max number of minutes to wait for input, kick_out()
120: after this much time */
121: /* Note: be careful to free entry answers */
122:
123: /* ------------------------------------------------------------------------- */
124: /* WRITE OUTPUT (NICELY) TO THE SCREEN */
125: /* ------------------------------------------------------------------------- */
126: void /* RETURNS: (nothing) */
127: wrap(str) /* ARGUMENTS: */
128: char *str; /* Block of text to output */
129: { /* LOCAL VARIABLES: */
130: int y,x,len; /* Row,Col of screen */
131: int i, /* Next space */
132: j; /* Next char to print */
133: len=strlen(str);
134: for (i=j=0; i<len; i++) {
135: getyx(stdscr,y,x);
136: while (i<len && !isspace(str[i])) i++;
137: if (x+i-j > 78) addch('\n');
138: while (j<=i) addch(str[j++]);
139: }
140: }
141: int
142: total_lines(char *str)
143: {
144: int len, lines_cnt=1;
145: int i, j, x=0;
146:
147: len=strlen(str);
148: for(i=j=0;i<len;i++) {
149: while (i<len && !isspace(str[i])) i++;
150: if (x+i-j > 78) { lines_cnt++; x = 0; }
151: while (j<=i) { x++; if(str[j] == '\n') {lines_cnt++; x=0; } j++; }
152: }
153: return (lines_cnt);
154: }
155:
156: /* --------------------------------------------- */
157: /* */
158: #define LINES_PER_SCREEN 20
159:
160: int display_prob_scr(char *str,int scr_idx)
161: {
162: int len, lines_cnt=0;
163: int i,j,y=0,x=0;
164: int break_pt, onscreen_pr;
165: int second_scr=0;
166:
167: if( str != NULL ) {
168: lines_cnt = total_lines(str);
169: if( lines_cnt > LINES_PER_SCREEN ) {
170: second_scr = 1;
171: } else {
172: scr_idx = 1;
173: }
174: if( scr_idx == 1 ) {
175: break_pt = LINES_PER_SCREEN + 1;
176: } else { /* which line to break the problem text into two screens */
177: if(lines_cnt>=40) { break_pt = LINES_PER_SCREEN; } else {
178: if(lines_cnt==39) { break_pt = LINES_PER_SCREEN - 1; } else {
179: if(lines_cnt==38) { break_pt = LINES_PER_SCREEN - 2; } else {
180: break_pt = LINES_PER_SCREEN - 3;
181: }
182: }
183: }
184: }
185:
186: #ifdef LOGIN_DBUG
187: fprintf(dfp,"DISPLAY SCR IDX=%d total LineCnt=%d Line Break= %d:\n",scr_idx,lines_cnt,break_pt); fflush(dfp);
188: #endif
189:
190: /* start to display the text on screen */
191:
192: lines_cnt = 1; x = y =0;
193: len=strlen(str);
194: #ifdef LOGIN_DBUG
195: fprintf(dfp,"SCR IDX=%d,leng=%d[[\n",scr_idx,len);
196: fflush(dfp);
197: #endif
198: for(i=j=0;i<len;i++) {
199: if( ( (scr_idx==1) && (lines_cnt < break_pt)) ||
200: ((scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN))) ) {
201: getyx(stdscr,y,x);
202: /* if (x2>=x) x=x2; else x=x2+80;*/
203: }
204: while (i<len && !isspace(str[i])) i++;
205: onscreen_pr = 0;
206: #ifdef LOGIN_DBUG
207: fprintf(dfp,"\n[NewWord line=%d,x=%d,i=%d,j=%d,y=%d]",lines_cnt,x,i,j,y);
208: #endif
209: if (x+i-j > 78) { /* line break */
210: if( (scr_idx==1) && (lines_cnt < break_pt) ) {
211: addch('\n'); onscreen_pr = 1;
212: #ifdef LOGIN_DBUG
213: fprintf(dfp,"\n[LineCnt=%d,x=%d,i=%d,j=%d]",lines_cnt,x,i,j);
214: #endif
215: }
216: if( (scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN)) ) {
217:
218: addch('\n'); onscreen_pr = 1;
219: #ifdef LOGIN_DBUG
220: fprintf(dfp,"\n[LineCnt=%d,x=%d,i=%d,j=%d]",lines_cnt,x,i,j);
221: #endif
222: }
223: lines_cnt++;
224: if(onscreen_pr == 0 ) {
225: x=0;
226: }
227: }
228: while (j<=i) { /* display on screen */
229: onscreen_pr = 0;
230: if( (scr_idx==1) && (lines_cnt < break_pt) ) {
231: addch(str[j]); /* display that character */
232: onscreen_pr = 1;
233: #ifdef LOGIN_DBUG
234: fprintf(dfp,"%c",str[j]);
235: #endif
236: }
237: if( (scr_idx==2) && (lines_cnt > break_pt) && (lines_cnt <= (break_pt+LINES_PER_SCREEN)) ) {
238:
239: addch(str[j]); onscreen_pr = 1;
240: #ifdef LOGIN_DBUG
241: fprintf(dfp,"%c",str[j]);
242: #endif
243: }
244: if( str[j] == '\n' ) {
245:
246: #ifdef LOGIN_DBUG
247: fprintf(dfp,"<LineCnt=%d>[j=%d]",lines_cnt,j);
248: #endif
249: if(onscreen_pr == 0 ) {
250: x = 0;
251: }
252: lines_cnt++;
253: }
254: if(onscreen_pr == 0 ) {
255: x++;
256: }
257: j++;
258: }
259: }
260: #ifdef LOGIN_DBUG
261: fprintf(dfp,"\n]]"); fflush(dfp);
262: #endif
263:
264: }
265: return (second_scr);
266:
267: }
268:
269: /* ------------------------------------------------------------------------- */
270: /* DISPLAY FAREWELL MESSAGE WHEN USER GOT KICKED OUT */
271: /* ------------------------------------------------------------------------- */
272: void /* RETURNS: (nothing) */
273: #ifdef __sun
274: kick_out(int sig)
275: #else
276: kick_out()
277: #endif
278:
279: { /* LOCAL VARIABLES: */
280: FILE *fp; /* Goodbye file pointer */
281: char buf[255]; /* Input buffer */
282:
283: /* DISPLAY EXIT MESSAGE */
284: CLEAR();
285: if ((fp=fopen("goodbye.msg","r"))!=NULL) {
286: while (fgets(buf,255,fp))
287: addstr(buf);
288: fclose(fp);
289: }
290: sprintf(buf, "This message will last for only %d seconds.",g_delay);
291: mvaddstr(22,20,buf); refresh();
292: sleep(g_delay);
293: /* mypause(22,20); */
294:
295: /* CURSES RESTORATION */
296: resetty(); endwin();
297: exit(1);
298: }
299:
300:
301: /* ------------------------------------------------------------------------- */
302: /* GET INPUT (NICELY) FROM A PLACE ON THE SCREEN */
303: /* ------------------------------------------------------------------------- */
304: void /* RETURNS: (nothing) */
305: get_input(y,x,str,inmax) /* ARGUMENTS: */
306: int y,x; /* Row,Col of screen to start */
307: char *str; /* String buffer to fill in */
308: int inmax; /* Maximum number of characters */
309: { /* LOCAL VARIABLES: */
310: int i=0,cx,cy; /* Position in buffer */
311: char c; /* Input character */
312:
313: if (y && x) move(y,x);
314: CLRTOEOL();
315: cx = x; cy = y;
316: #if defined( __alpha) || defined(__sun)
317: while (1) {
318: alarm(g_max_delay*60);
319: c=getch();
320: if (c==10 || c==13) break;
321: else if (c==8 || c==16 || c==127) {
322: if (i>0) {
323: i--; cx--; echo(); move(cy,cx);
324: delch(); insch(' '); refresh(); noecho();
325: } else
326: beep();
327: } else if (i>=inmax) { beep(); } else {
328: str[i++] = c; cx++;
329: echo(); ADDCH(c); noecho();
330: }
331: }
332: #else
333: while (1) {
334: alarm(g_max_delay*60);
335: c=getch();
336: if (c==10 || c==13) break;
337: else if (c==8 || c==16 || c==127) {
338: if (i>0) {
339: i--; printf("%c %c",8,8); refresh();
340: } else printf("%c",7);
341: } else if (i>=inmax) { printf("%c",7);
342: } else {
343: str[i++] = c; ADDCH(c);
344: }
345: }
346: #endif
347: str[i]=0;
348: }
349:
350:
351: void /* RETURNS: (nothing) */
352: get_xinput(y,x,str,inmax)/* ARGUMENTS: */
353: int y,x; /* Row,Col of screen to start */
354: char *str; /* String buffer to fill in */
355: int inmax; /* Maximum number of characters */
356: { /* LOCAL VARIABLES: */
357: int i=0,cx,cy; /* Position in buffer */
358: char c; /* Input character */
359:
360:
361: for(i=0;i<inmax;i++) { move(y,x+i); ADDCH(' '); }
362: i=0;
363: if (y && x) move(y,x);refresh();
364: cx = x; cy = y;
365: #if defined( __alpha) || defined(__sun)
366: while (1) {
367: alarm(g_max_delay*60);
368: c=getch();
369: if (c==10 || c==13) break;
370: else if (c==8 || c==16 || c==127) {
371: if (i>0) {
372: i--; cx--; echo(); move(cy,cx);
373: delch(); insch(' '); refresh(); noecho();
374: } else
375: beep();
376: } else if (i>=inmax) { beep(); } else {
377: str[i++] = c; cx++;
378: echo(); ADDCH(c); noecho();
379: }
380: }
381: #else
382: while (1) {
383: alarm(g_max_delay*60);
384: c=getch();
385: if (c==10 || c==13) break;
386: else if (c==8 || c==16 || c==127) {
387: if (i>0) {
388: i--; printf("%c %c",8,8); refresh();
389: } else printf("%c",7);
390: } else if (i>=inmax) { printf("%c",7);
391: } else {
392: str[i++] = c; ADDCH(c);
393: }
394: }
395: #endif
396: str[i]=0;
397: }
398:
399: /*
400: void
401: input_pin(y,x,str,inmax)
402: int y,x;
403: char *str;
404: int inmax;
405: {
406: int i=0,cx,cy;
407: char c;
408:
409: if (y && x) move(y,x);
410: cx = x; cy = y;
411: CLRTOEOL();
412: #ifdef __alpha
413: while (1) {
414: c=getch();
415: if (c==10 || c==13) break;
416: else if (c==8 || c==16 || c==127) {
417: if (i>0) {
418: i--; cx--; echo(); move(cy,cx);
419: delch(); insch(' '); refresh(); noecho();
420: } else
421: beep();
422: } else if (i>=inmax) { beep(); } else {
423: str[i++] = c; cx++;
424: echo(); ADDCH('*'); noecho();
425: }
426: }
427: #else
428: while (1) {
429: c=getch();
430: if (c==10 || c==13) break;
431: else if (c==8 || c==16 || c==127) {
432: if (i>0) {
433: i--; printf("%c %c",8,8); refresh();
434: } else printf("%c",7);
435: } else if (i>=inmax) { printf("%c",7);
436: } else {
437: str[i++] = c; ADDCH('*');
438: }
439: }
440: #endif
441: str[i]=0;
442: }
443: */
444:
445: /* ------------------------------------------------------------------------- */
446: /* PAUSE UNTIL USER HITS A KEY */
447: /* ------------------------------------------------------------------------- */
448: void /* RETURNS: (nothing) */
449: mypause(y,x) /* ARGUMENTS: */
450: int y,x; /* Row,Col of screen */
451: { /* LOCAL VARIABLES: */
452: char c; /* Input character */
453:
454: mvaddstr(y,x,"Press ENTER/RETURN to continue");
455: get_input(y,x+30,&c,0);
456: }
457:
458: /* ------------------------------------------------------------------------- */
459: /* DISPLAY FAREWELL MESSAGE WHEN USER LOGS OUT */
460: /* ------------------------------------------------------------------------- */
461: void /* RETURNS: (nothing) */
462: properly_logout(student_number) /* ARGUMENTS: */
463: char *student_number;
464: { /* LOCAL VARIABLES: */
465: FILE *fp; /* Goodbye file pointer */
466: char buf[255]; /* Input buffer */
467: char *out_t;
468: char filename[FILE_NAME_LENGTH];
469:
470: /* DISPLAY EXIT MESSAGE */
471: CLEAR();
472: time(&log_out_time);
473: out_t=ctime(&log_out_time);
474: out_t[ strlen(out_t)-1 ]=0; /* Trash newline */
475:
476: sprintf(filename,"records/duration.db");
477: if ((fp=fopen(filename,"a"))==NULL) {
478: printf("Error: can't open duration file\n");
479: return;
480: }
481: flockstream(fp);
482: fprintf(fp,"%s\t%s\t%s\t%s\n",student_number,in_tty,in_t,out_t);
483: funlockstream(fp);
484: fclose(fp);
485:
486:
487: if ((fp=fopen("goodbye.msg","r"))!=NULL) {
488: while (fgets(buf,255,fp))
489: addstr(buf);
490: fclose(fp);
491: }
492: /* mypause(22,20); */
493: #ifndef NO_DUP_CHECK
494: logout_check(student_number);
495: #endif
496:
497: #ifndef LOGIN_DBUG
498: sprintf(buf, "This message will last for only %d seconds.",g_delay);
499: mvaddstr(22,20,buf); refresh();
500: sleep(g_delay);
501: #endif
502:
503: /* CURSES RESTORATION */
504: resetty(); endwin();
505: exit(1);
506: }
507: /* ------------------------------------------------------------------------- */
508: /* Forbid duplicate login */
509: /* ------------------------------------------------------------------------- */
510: void /* RETURNS: (nothing) */
511: dup_login_out() /* ARGUMENTS: */
512: { /* LOCAL VARIABLES: */
513: FILE *fp; /* Goodbye file pointer */
514: char buf[255]; /* Input buffer */
515:
516: /* DISPLAY EXIT MESSAGE */
517: CLEAR();
518: if ((fp=fopen("third-login.msg","r"))!=NULL) {
519: while (fgets(buf,255,fp)) addstr(buf);
520: fclose(fp);
521: }
522: /* mypause(22,20);*/
523: /* CURSES RESTORATION */
524: sprintf(buf, "This message will last for only %d seconds.",g_delay);
525: mvaddstr(22,20,buf); refresh();
526: sleep(g_delay);
527: resetty(); endwin();
528: exit(1);
529: }
530:
531: void /* RETURNS: (nothing) */
532: dup_login_warning()/* ARGUMENTS: */
533: { /* LOCAL VARIABLES: */
534: FILE *fp; /* Welcome file pointer */
535: char buf[255]; /* Input buffer */
536:
537: CLEAR();
538: if ((fp=fopen("second-login.msg","r"))!=NULL) {
539: while (fgets(buf,255,fp))
540: addstr(buf);
541: fclose(fp);
542: }
543: mypause(22,20);
544: }
545:
546: /* ------------------------------------------------------------------------- */
547: /* ALLOW USER TO LOG IN */
548: /* ------------------------------------------------------------------------- */
549: char /* RETURNS: Student number */
550: *login(maxset,section) /* ARGUMENTS: */
551: int *maxset; /* Set number */
552: int *section; /* Section number */
553: { /* LOCAL VARIABLES: */
554: char *student_number; /* Student number */
555: int guess, /* User-entered PIN */
556: login_set; /* Set for which PIN is valid */
557: int login_section = 0;
558: char buff[20]; /* Input buffer */
559: T_entry entry;
560: time_t curtime; /* Current time */
561: int leng;
562: T_student student_data;
563:
564: #define D_S_NUM_Y 11
565: #define D_S_NUM_X 13
566:
567: #define D_PIN_Y (D_S_NUM_Y + 2)
568: #define D_PIN_X (D_S_NUM_X + 10)
569: #define D_EXIT_Y (D_S_NUM_Y + 5)
570: #define D_EXIT_X (D_S_NUM_X + 6)
571: #define IN_S_NUM_Y (D_S_NUM_Y)
572: #define IN_S_NUM_X (D_S_NUM_X + 16)
573: #define IN_PIN_Y (D_PIN_Y)
574: #define IN_PIN_X (D_PIN_X + 9)
575: #define M_INVALID_Y (IN_PIN_Y + 1)
576: #define M_INVALID_X (IN_PIN_X)
577:
578: student_number = (char *)malloc( (MAX_STUDENT_NUMBER+4)*sizeof(char));
579: /* LOOP UNTIL WE ARE LEGALLY LOGGED IN */
580: do {
581: mvaddstr(D_S_NUM_Y,D_S_NUM_X,"STUDENT NUMBER: ");
582: mvaddstr(D_PIN_Y,D_PIN_X,"CAPA ID: ");
583: mvaddstr(D_EXIT_Y,D_EXIT_X,"To exit system, just hit ENTER/RETURN");
584:
585: #ifndef NO_PIN
586: /* LOOP UNTIL WE HAVE A STUDENT NUMBER AND PIN */
587: do {
588: #endif /* NO_PIN */
589:
590: /* LOOP UNTIL A LEGAL STUDENT NUMBER IS ENTERED */
591: do {
592: get_input(IN_S_NUM_Y,IN_S_NUM_X,buff, MAX_STUDENT_NUMBER);
593: #ifdef __sun
594: if (!strlen(buff)) kick_out(0);
595: #else
596: if (!strlen(buff)) kick_out();
597: #endif
598: sscanf(buff,"%s",student_number); leng = strlen(student_number);
599: } while (leng < MAX_STUDENT_NUMBER);
600:
601: #ifndef NO_PIN
602: get_input(IN_PIN_Y,IN_PIN_X,buff,MAX_PIN_CHAR);
603: #ifdef __sun
604: if (!strlen(buff)) kick_out(0);
605: #else
606: if (!strlen(buff)) kick_out();
607: #endif
608: sscanf(buff,"%d",&guess);
609: } while (guess<1);
610: #endif /* NO_PIN */
611:
612: student_number[strlen(student_number)] = 0;
613: /* VERIFY PIN */
614:
615: #ifdef NO_PIN
616: login_set = 1;
617: #else
618: login_set = capa_PIN(student_number,999,guess);
619: #endif /* No_PIN */
620:
621: #ifdef LOGIN_DBUG
622: fprintf(dfp,"LOGIN:S=%s,Guess=%04d,Actual Pin=%04d,set=%d\n",
623: student_number,guess,capa_PIN(student_number,1, 0), login_set);
624: fprintf(dfp," PIN=%04d,%04d,%04d,%04d,%04d\n",
625: capa_PIN(student_number,1, 0), capa_PIN(student_number,2, 0),capa_PIN(student_number,3, 0),
626: capa_PIN(student_number,4, 0), capa_PIN(student_number,5, 0));
627: fflush(dfp);
628: #endif
629: if (!login_set) {
630: mvaddstr(M_INVALID_Y,M_INVALID_X, "INVALID LOGIN ");
631: } else {
632: if ( login_set > 99 ) {
633: mvaddstr(M_INVALID_Y,M_INVALID_X, "INCORRECT PIN "); login_set = 0;
634: }
635: if ( capa_get_student(student_number,&student_data) == 0 ) {
636: mvaddstr(M_INVALID_Y,M_INVALID_X,"NO SUCH STUDENT"); login_set=0;
637: } else {
638: login_section = student_data.s_sec;
639: #ifdef LOGIN_DBUG
640: fprintf(dfp, " Student in section %d\n",login_section);fflush(dfp);
641: #endif
642: time(&curtime);
643: if( capa_check_date(CHECK_OPEN_DATE,student_number,
644: login_section,login_set) < 0 ) {
645: mvaddstr(M_INVALID_Y,M_INVALID_X,"NOT YET OPEN!"); login_set=0;
646: }
647: }
648: }
649: } while ( !login_set );
650: #ifdef LOGIN_DBUG
651: fprintf(dfp, "DEBUG:%s Access granted through set %d section %d\n",
652: student_number, login_set, login_section); fflush(dfp);
653: #endif
654: #ifndef NO_DUP_CHECK
655: switch( login_check(student_number)) {
656: case 0:
657: mvaddstr(M_INVALID_Y,M_INVALID_X,"CANNOT LOGIN"); dup_login_out();
658: break;
659: case 1:
660: mvaddstr(M_INVALID_Y,M_INVALID_X,"FIRST TIME LOGIN");
661: break;
662: case 2:
663: mvaddstr(M_INVALID_Y,M_INVALID_X,"SECOND TIME LOGIN"); dup_login_warning( );
664: break;
665: case -1:
666: #ifdef __sun
667: mvaddstr(M_INVALID_Y,M_INVALID_X,"FILE ERROR"); kick_out(0);
668: #else
669: mvaddstr(M_INVALID_Y,M_INVALID_X,"FILE ERROR"); kick_out();
670: #endif
671: break;
672: }
673: #endif /* NO_DUP_CHECK */
674: capa_get_entry(&entry,student_number,login_set);
675: (*maxset) = login_set;
676: (*section) = login_section;
677: capa_mfree(entry.answers);
678: capa_mfree(entry.tries);
679: return (student_number);
680: }
681:
682: /* ------------------------------------------------------------------------- */
683: /* LOG ANSWERS TO A FILE WITH TIMESTAMP */
684: /* ------------------------------------------------------------------------- */
685: int /* RETURNS: error code */
686: log_attempt(student_number,set,section,log_string) /* ARGUMENTS: */
687: char student_number[MAX_STUDENT_NUMBER+1]; /* Student number */
688: int set; /* Set number */
689: int section; /* Section number */
690: char *log_string; /* Answer string to log */
691: { /* LOCAL VARIABLES: */
692: char filename[FILE_NAME_LENGTH], /* Log filename buffer */
693: *ct; /* Current time string */
694: FILE *fp; /* Log file pointer */
695: time_t t; /* Timestamp for log */
696:
697: /* OPEN LOG FILE */
698:
699: sprintf(filename,"records/log%d.db",set);
700: if ((fp=fopen(filename,"a"))==NULL) {
701: printf("Error: can't open log file\n");
702: return -1;
703: }
704:
705: /* CREATE LOG ENTRY */
706: time(&t);
707: ct=ctime(&t);
708: ct[ strlen(ct)-1 ]=0; /* Trash newline */
709: fprintf(fp,"%s %s %s\n",student_number,ct,log_string); fflush(fp);
710: fclose(fp);
711: return 0;
712: }
713:
714: int log_submissions(student_number,set,log_string)
715: char student_number[MAX_STUDENT_NUMBER+1];
716: int set;
717: char *log_string;
718: {
719: char filename[FILE_NAME_LENGTH], timeStr[FILE_NAME_LENGTH],buf2[MAX_BUFFER_SIZE];
720: FILE *fp;
721: time_t t;
722: struct tm *tmtime;
723: int do_log_submissions=1,result;
724: char buf[MAX_BUFFER_SIZE];
725:
726: result=read_capa_config("do_log_submissions",buf);
727: if (result != 0 && result != -1) {
728: if (strcasecmp(buf2,"no")==0) {
729: do_log_submissions=0;
730: }
731: }
732: if (!do_log_submissions) return 0;
733:
734: sprintf(filename,"records/submissions%d.db",set);
735: if ((fp=fopen(filename,"a"))==NULL) {
736: return (-1);
737: }
738:
739: /* CREATE LOG ENTRY */
740: time(&t);
741: tmtime=localtime(&t);
742: strftime(timeStr,FILE_NAME_LENGTH,"%d/%m %X",tmtime);
743: /*ct[ strlen(ct)-1 ]=0;*/ /* Trash newline */
744: protect_log_string(log_string);
745: fprintf(fp,"%s\t%s\t%s\n",student_number,timeStr,log_string); fflush(fp);
746: fclose(fp);
747: return (0);
748: }
749:
750: #define C_FORWARD 1
751: #define C_EXIT 2
752: #define C_MENU 3
753: #define C_HINT 4
754: #define C_EXPLAIN 5
755: #define C_ANSWER 6
756: #define C_JUMP 7
757: #define C_DONTCARE 8
758: #define C_BACKWARD 9
759: #define C_TIME 10
760: #define C_NEXTSCR 11
761: #define C_PREVSCR 12
762: #define C_SUBJANS 13
763:
764: /* ------------------------------------------------------------------------- */
765: /* DISPLAY SUMMARY OF SCORES FOR THE TERM */
766: /* ------------------------------------------------------------------------- */
767: void /* RETURNS: (nothing) */
768: term_summary(student_number,set,section,type) /* ARGUMENTS: */
769: char *student_number; /* Student Number */
770: int set; /* Set number */
771: int *section; /* Section Number */
772: int type;
773: { /* LOCAL VARIABLES: */
774: int set_idx, /* Set counter */
775: i, /* Question counter */
776: tmp, /* Question correct flag */
777: set_score, /* Score on a set */
778: term_score=0, /* Total points received */
779: term_total=0, /* Total points possible */
780: result,
781: tot_num_sets=0;
782: T_entry entry; /* Database entry for a set */
783: char buf[MAX_BUFFER_SIZE], buf2[MAX_BUFFER_SIZE];
784: T_header header; /* Problem set header */
785: int topset=1, /* First displayed set */
786: bottomset, /* Last displayed set */
787: done=0, /* Done flag */
788: line, col;
789: int probs_in_set[MAX_BUFFER_SIZE],/* # problem set questions */
790: start_at[MAX_BUFFER_SIZE],
791: valid_wgt[SMALL_LINE_BUFFER],
792: a_valid_wgt,set_start_line,
793: usr_command,inhibit_response;
794:
795: /* CALCULATE TERM TOTALS */
796: start_at[0] = -2;
797: probs_in_set[0]= 0;
798: for (set_idx=1; set_idx<=set; set_idx++) {
799: if (capa_get_header(&header,set_idx)) return;
800: if ( capa_check_date(CHECK_OPEN_DATE,student_number,*section,set_idx) < 0 )
801: continue;
802: tot_num_sets++;
803: capa_get_entry(&entry,student_number,set_idx);
804: sscanf(header.num_questions,"%d", &(probs_in_set[set_idx]) );
805: start_at[set_idx] = start_at[set_idx-1]+2*(1+probs_in_set[set_idx-1]/50);
806: if ((start_at[set_idx]%12)+2*(1+probs_in_set[set_idx]/50) > 12)
807: start_at[set_idx] = 12*(1+start_at[set_idx]/12);
808: valid_wgt[set_idx] = 0;
809: for (i=0; i<probs_in_set[set_idx]; i++) {
810: valid_wgt[set_idx] += (header.weight[i] - '0');
811: if((entry.answers[i]=='Y') || (entry.answers[i]=='y'))
812: term_score += (header.weight[i]-'0');
813: if((entry.answers[i]=='E') || (entry.answers[i]=='e'))
814: valid_wgt[set_idx] -= (header.weight[i] - '0');
815: if((entry.answers[i]>='0') && (entry.answers[i]<='9'))
816: term_score += (entry.answers[i] - '0');
817: }
818: term_total += valid_wgt[set_idx];
819: capa_mfree(header.weight);
820: capa_mfree(header.partial_credit);
821: capa_mfree(entry.answers);
822: capa_mfree(entry.tries);
823: }
824:
825: /* FIND TOPSET */
826: line = 12*(start_at[set]/12); /* Top line # of last screen */
827: for (topset=set; topset>1 && start_at[topset-1]>=line; topset--);
828:
829: /* SHOW HEADER */
830: CLEAR();
831: switch(type) {
832: case TERM_SUMMARY: mvaddstr(1,30,"TERM SUMMARY"); break;
833: case EXAM_SUMMARY: mvaddstr(1,30,"EXAM SUMMARY"); break;
834: case QUIZ_SUMMARY: mvaddstr(1,30,"QUIZ SUMMARY"); break;
835: }
836: mvaddstr(3,22," 1 2 3 4 5");
837: mvaddstr(4,22,"12345678901234567890123456789012345678901234567890");
838:
839: /* DISPLAY COMMAND MENU */
840: mvaddstr(21,1,"Enter a command from the list below and press ENTER/RETURN COMMAND:");
841: mvaddstr(22,1,"M =Go to main menu N =Next Page P =Prev Page");
842: /* mvaddstr(22,1,"X =eXit M =Go to main menu N =Next Page P =Prev Page"); */
843: refresh();
844:
845: /* SHOW TOTALS */
846: /* if capalogin_show_summary_score is set to none don't show it */
847: if (term_total > 0 ) {
848: sprintf(buf,"%d sets, total=%3d/%3d (%d%%)", tot_num_sets, term_score, term_total,
849: 100*term_score/term_total);
850: } else {
851: sprintf(buf,"%d sets, total=%3d/%3d", tot_num_sets, term_score, term_total);
852: }
853: result=read_capa_config("capalogin_show_summary_score",buf2);
854: if (result != 0 && result != -1) {
855: if (strcasecmp(buf2,"none")==0) {
856: } else {
857: mvaddstr(19,1,buf);
858: }
859: } else {
860: mvaddstr(19,1,buf);
861: }
862:
863: /* LOOP UNTIL DONE */
864: while (!done) {
865: /* PRINT 1 LINE SUMMARY PER SET */
866: line=5;
867: for (set_idx=topset; set_idx<=set; set_idx++) {
868: /* don't show summary for set if inhibit response is set*/
869: inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set_idx,*section);
870: if (inhibit_response > 0) continue;
871: if ( capa_check_date(CHECK_OPEN_DATE,student_number,*section,set_idx) < 0 )
872: continue;
873: set_score=0;
874: set_start_line=line;
875: /* Stop if not enough lines to summarize set */
876: if (line+2*(probs_in_set[set_idx]/50)>16) break;
877: capa_get_header(&header,set_idx);
878: capa_get_entry(&entry,student_number,set_idx);
879: a_valid_wgt = 0;
880: for (i=0, col=0; i<probs_in_set[set_idx]; i++) {
881: tmp=0; a_valid_wgt += (header.weight[i] - '0');
882: move(line, 22+col); addch(entry.answers[i]);
883: move(line+1,22+col); addch(header.weight[i]);
884: switch(entry.answers[i]) {
885: case 'Y': tmp=header.weight[i] -'0'; break; /* Answer correct */
886: case 'y': tmp=header.weight[i] -'0'; break; /* Grading correct */
887: case '-': break; /* Not answered */
888: case 'N': break; /* Answer incorrect */
889: case 'n': break; /* Grading incorrect */
890: case 'e': a_valid_wgt -= (header.weight[i] - '0'); break; /* Excuse */
891: case 'E': a_valid_wgt -= (header.weight[i] - '0'); break; /* Excuse */
892: default : if( entry.answers[i] >= '0' && entry.answers[i] <= '9' ) {
893: tmp = entry.answers[i] - '0';
894: }
895: break;
896: }
897: set_score += tmp; col++;
898: if (!((i+1)%50)) { line += 2; col = 0; }
899: }
900: capa_mfree(header.weight);
901: capa_mfree(header.partial_credit);
902: capa_mfree(entry.answers);
903: capa_mfree(entry.tries);
904: move(line, 22+col); CLRTOEOL();
905: move(line+1, 22+col); CLRTOEOL();
906: if(a_valid_wgt == 0) {
907: set_score=0;
908: sprintf(buf,"%3d:%3d/%3d(%3d%%) ",set_idx,set_score,a_valid_wgt,set_score);
909: mvaddstr(set_start_line,1,buf);
910: } else {
911: sprintf(buf,"%3d:%3d/%3d(%3d%%) ",set_idx,set_score,a_valid_wgt,100*set_score/a_valid_wgt);
912: mvaddstr(set_start_line,1,buf);
913: }
914: line += 2;
915: }
916: bottomset=set_idx-1;
917:
918: /* Blank out any extra lines */
919: if (line < 16) {
920: for (set_idx=line; set_idx<=16; set_idx++) {
921: move(set_idx,1);
922: CLRTOEOL();
923: }
924: }
925:
926: /* PROCESS USER COMMAND */
927: get_input(21,72,buf,1);
928: if(!strlen(buf)) { usr_command = C_FORWARD; } else {
929:
930: switch(toupper(buf[0])) {
931: /* case 'X': usr_command=C_EXIT; break; */
932: case 'M': usr_command=C_MENU; break;
933: case 'P': usr_command=C_BACKWARD; break;
934: default : usr_command=C_FORWARD; break;
935: }
936: }
937:
938:
939: switch(usr_command) {
940: case C_DONTCARE: break;
941: case C_FORWARD: /* Forwards */
942: if (bottomset<set) { topset=bottomset+1; } else { done=1; }
943: break;
944:
945: case C_BACKWARD: /* Backwards */
946: if (topset<2) break;
947: line = 12*(start_at[topset-1]/12); /* Top line # of prev screen */
948: for (; topset>1 && start_at[topset-1]>=line; topset--);
949: break;
950:
951: case C_MENU: /* Menu */
952: done=1;
953: break;
954: case C_EXIT: /* Exit */
955: properly_logout(student_number);
956: break;
957: default: /* Invalid command */
958: break;
959: }
960: }
961: }
962:
963: void
964: display_hint(char *h)
965: {
966:
967: CLEAR();
968:
969: wrap(h);
970: mypause(22,20);
971: }
972:
973: #define A_ROW 20
974: #define S_ROW 21
975: #define O_ROW 22
976: #define X_ROW 23
977:
978: #define A_COL 14
979: #define S_COL 46
980: #define H_COL 24
981: #define E_COL 39
982: #define X_COL 8
983: #define R_COL 57
984: #define U_ANS_CHAR 32
985:
986: /* =============================================================================
987: 0001234567890123456789012345678901234567890123456789012345678901234567890123456789
988: A
989: S1OPTION/ANSWER 12345678901234 ----- *Unanswered
990: O2Options :M = Main Menu :7 = go to #7 :N = Next screen RETURN = Enter/Execute
991: X3 :X = eXit :H = Show Hint :E = Explain RETURN = Next Problem
992: 0123456789012345678901234567890123456789012345678901234567890
993: ^ ^ ^ ^ ^ ^
994: X A H E S R
995: */
996: int show_prior_response(Problem_t *p,int hgr,int prev_ans,int tried,int *allow_h)
997: {
998: char *c_answer_str, tmp_str[MAX_BUFFER_SIZE];
999: char *response="Incorrect",*answered="Answered";
1000: int can_answer;
1001:
1002: if( hgr == '0' || p->ans_type==ANSWER_IS_SUBJECTIVE) {
1003: switch(prev_ans) {
1004: case 'Y': can_answer=NAY; *allow_h=1;
1005: c_answer_str = answers_string(ANSWER_STRING_MODE,p);
1006: move(A_ROW,A_COL); clrtoeol();
1007: mvaddstr(A_ROW,A_COL,c_answer_str); capa_mfree(c_answer_str);
1008: move(S_ROW,S_COL); clrtoeol();
1009: mvaddstr(S_ROW,S_COL,"**Correct "); break;
1010: case 'y': can_answer=NAY; *allow_h=1;
1011: c_answer_str = answers_string(ANSWER_STRING_MODE,p);
1012: move(A_ROW,A_COL); clrtoeol();
1013: mvaddstr(A_ROW,A_COL,c_answer_str); capa_mfree(c_answer_str);
1014: move(S_ROW,S_COL); clrtoeol();
1015: mvaddstr(S_ROW,S_COL,"*Hand-graded Correct "); break;
1016: case '-': can_answer=YAK; move(S_ROW,S_COL); clrtoeol();
1017: mvaddstr(S_ROW,S_COL,"*Unanswered "); break;
1018: case 'E': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
1019: mvaddstr(S_ROW,S_COL,"*Excused "); break;
1020: case 'e': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
1021: mvaddstr(S_ROW,S_COL,"*Excused "); break;
1022: case 'n': can_answer=NAY; move(S_ROW,S_COL); clrtoeol();
1023: mvaddstr(S_ROW,S_COL,"*Hand-graded Incorrect "); break;
1024: case '0': case '1': case '2': case '3': case '4': case '5':
1025: case '6': case '7': case '8': case '9':
1026: response=answered;
1027: case 'N': if ( tried < p->tries ) {
1028: can_answer=YAK;
1029: if( (p->tries - tried) == 1 ) {
1030: sprintf(tmp_str,"*%s, ONE try left!!",response);
1031: } else {
1032: sprintf(tmp_str,"*%s, tries %2d/%2d ",response,tried,p->tries);
1033: }
1034: } else {
1035: can_answer=NAY;
1036: sprintf(tmp_str, "*%s, no more tries",response);
1037: }
1038: move(S_ROW,S_COL); clrtoeol();
1039: mvaddstr(S_ROW,S_COL,tmp_str);
1040: if( (can_answer == YAK) && (p->ans_op == ANS_AND) && (p->ans_cnt > 1)) {
1041: sprintf(tmp_str, " Entering answer 1 of %3d ",p->ans_cnt);
1042: mvaddstr(A_ROW,S_COL,tmp_str);
1043: }
1044: break;
1045: }
1046: } else { /* hand graded question */
1047: can_answer=NAY;
1048: move(S_ROW,S_COL); clrtoeol();
1049: mvaddstr(S_ROW,S_COL,"*Hand-graded question ");
1050: }
1051: /* ------------------------------------------------------------------ */
1052: if (*allow_h &&
1053: p->hint &&
1054: (
1055: ( p->show_hint <= tried ) ||
1056: ( prev_ans == 'y' ) ||
1057: ( prev_ans == 'Y' )
1058: )
1059: ) {
1060: mvaddstr(X_ROW,H_COL,":H = Show Hint");
1061: } else {
1062: *allow_h = 0;
1063: }
1064: if (p->next)
1065: mvaddstr(X_ROW,R_COL,"RETURN = Next Problem");
1066: else
1067: mvaddstr(X_ROW,R_COL,"RETURN = Main Menu ");
1068:
1069: return (can_answer);
1070:
1071: }
1072: int show_prior_inhibited_response(Problem_t *p,int hgr,int prev_ans,int tried,
1073: int *allow_h)
1074: {
1075: char tmp_str[MAX_BUFFER_SIZE];
1076: int can_answer;
1077:
1078: if( hgr == '0' ) {
1079: switch(prev_ans) {
1080: case '-': can_answer=YAK; move(S_ROW,S_COL); clrtoeol();
1081: mvaddstr(S_ROW,S_COL,"*Unanswered "); break;
1082: case 'E':
1083: case 'e':
1084: case 'n':
1085: case 'y':
1086: case 'Y':
1087: case 'N': if ( tried < p->tries ) {
1088: can_answer=YAK;
1089: if( (p->tries - tried) == 1 ) {
1090: sprintf(tmp_str,"*Answered, ONE try left!! ");
1091: } else {
1092: sprintf(tmp_str,"*Answered, tries %2d/%2d ",tried,p->tries);
1093: }
1094: } else {
1095: can_answer=NAY;
1096: sprintf(tmp_str, "*Answered, no more tries ");
1097: }
1098: move(S_ROW,S_COL); clrtoeol();
1099: mvaddstr(S_ROW,S_COL,tmp_str); break;
1100:
1101: }
1102: } else { /* hand graded question */
1103: can_answer=NAY;
1104: move(S_ROW,S_COL); clrtoeol();
1105: mvaddstr(S_ROW,S_COL,"*Hand-graded question ");
1106: }
1107: /* ------------------------------------------------------------------ */
1108: if (*allow_h && p->hint && ( p->show_hint <= tried)){
1109: mvaddstr(X_ROW,H_COL,":H = Show Hint");
1110: } else {
1111: *allow_h = 0;
1112: }
1113: if (p->next)
1114: mvaddstr(X_ROW,R_COL,"RETURN = Next Problem");
1115: else
1116: mvaddstr(X_ROW,R_COL,"RETURN = Main Menu ");
1117:
1118: return (can_answer);
1119:
1120: }
1121: /* -------------------------------------------- dbug --------------------- */
1122: void
1123: print_unit_components(FILE *fp,Unit_t *t)
1124: {
1125: Unit_E *ue_p;
1126:
1127: fprintf(fp," Unit::[%s] = %g * ", t->u_symbol, t->u_scale);
1128: for(ue_p=t->u_list; ue_p ; ue_p = ue_p->ue_nextp) {
1129: fprintf(fp,"(%g*%s^%g) ",ue_p->ue_scale,ue_p->ue_symbol,ue_p->ue_exp);
1130: }
1131: fprintf(fp,"\n"); fflush(fp);
1132:
1133: }
1134:
1135:
1136: /*#define ANSWER_STRING_LENG 64*/
1137: #define UNIT_STRING_LENG 64
1138: #define FORMAT_STRING_LENG 32
1139:
1140: /* ------------------------------------------------------------------- */
1141: int give_response(Problem_t *p,char **a,int cnt,int *tried,int *log_char)
1142: {
1143: int can_answer;
1144: char tmp_str[MAX_BUFFER_SIZE], *c_answer_str;
1145: char *error=NULL;
1146:
1147: switch( capa_check_answers(p,a,cnt,&error) ) {
1148:
1149: case EXACT_ANS: move(A_ROW,S_COL); clrtoeol();
1150: mvaddstr(A_ROW,S_COL,"*Yes Computer gets:");
1151: c_answer_str = answers_string(ANSWER_STRING_MODE, p);
1152: move(S_ROW,S_COL); clrtoeol();
1153: mvaddstr(S_ROW,S_COL,c_answer_str);
1154: capa_mfree((char *)c_answer_str);
1155: *log_char='Y'; can_answer=NAY;
1156: if( *tried < TRY_BOUND) (*tried)++;
1157: break;
1158: case APPROX_ANS:
1159: move(A_ROW,S_COL); clrtoeol();
1160: mvaddstr(A_ROW,S_COL,"*Yes Computer gets:");
1161: c_answer_str = answers_string(ANSWER_STRING_MODE, p);
1162: if(cnt == 1 ) {
1163: move(S_ROW,S_COL); clrtoeol();
1164: mvaddstr(S_ROW,S_COL,c_answer_str);
1165: } else { /* more than one answer to check ANS_AND */
1166: move(S_ROW,S_COL); clrtoeol();
1167: mvaddstr(S_ROW,S_COL,"*Yes Correct Answers See Above");
1168: move(A_ROW,A_COL); clrtoeol();
1169: mvaddstr(A_ROW,A_COL,c_answer_str);
1170: }
1171: capa_mfree((char *)c_answer_str);
1172: *log_char='Y'; can_answer=NAY;
1173: if(*tried < TRY_BOUND) (*tried)++;
1174: break;
1175: case WANTED_NUMERIC: move(S_ROW,S_COL); clrtoeol();
1176: mvaddstr(S_ROW,S_COL,"*Enter a Number Ans");
1177: *log_char='S'; can_answer=YAK;
1178: break;
1179: case SIG_FAIL: move(S_ROW,S_COL); clrtoeol();
1180: mvaddstr(S_ROW,S_COL,"*Adjust Sig. Figs. ");
1181: *log_char='S'; can_answer=YAK;
1182: capa_mfree(error);
1183: break;
1184: case UNIT_FAIL: move(S_ROW,S_COL); clrtoeol();
1185: mvaddstr(S_ROW,S_COL,"*Units incorrect ");
1186: *log_char='U'; can_answer=YAK;
1187: capa_mfree(error);
1188: break;
1189: case UNIT_NOTNEEDED: move(S_ROW,S_COL); clrtoeol();
1190: mvaddstr(S_ROW,S_COL,"*Only a number required");
1191: *log_char='U'; can_answer=YAK;
1192: capa_mfree(error);
1193: break;
1194: case NO_UNIT: move(S_ROW,S_COL); clrtoeol();
1195: mvaddstr(S_ROW,S_COL,"*Units required ");
1196: *log_char='u'; can_answer=YAK;
1197: break;
1198: case BAD_FORMULA:move(S_ROW,S_COL); clrtoeol();
1199: mvaddstr(S_ROW,S_COL,"*Unable to interpret formula");
1200: *log_char='F'; can_answer=YAK;
1201: break;
1202: case ANS_CNT_NOT_MATCH:
1203: move(S_ROW,S_COL); clrtoeol();
1204: mvaddstr(S_ROW,S_COL,"*Invalid number of answers");
1205: *log_char='C'; can_answer=YAK;
1206: break;
1207: case INCORRECT:
1208: if(*tried < TRY_BOUND) (*tried)++;
1209: if ( *tried < p->tries ) {
1210: can_answer=YAK;
1211: if( (p->tries - *tried) == 1 ) {
1212: sprintf(tmp_str,"*Incorrect, ONE try left!!");
1213: } else {
1214: sprintf(tmp_str,"*Incorrect, tries %2d/%2d ",*tried,p->tries);
1215: }
1216: } else {
1217: can_answer=NAY;
1218: sprintf(tmp_str, "*Incorrect, no more tries");
1219: }
1220: move(S_ROW,S_COL); clrtoeol();
1221: mvaddstr(S_ROW,S_COL, tmp_str);
1222: if( (can_answer == YAK) && (p->ans_op == ANS_AND) && (p->ans_cnt > 1) ) {
1223: sprintf(tmp_str, " Entering answer 1 of %3d ",p->ans_cnt);
1224: mvaddstr(A_ROW,S_COL,tmp_str);
1225: }
1226: *log_char='N';
1227: break;
1228: }
1229:
1230: return (can_answer);
1231: }
1232:
1233: int give_inhibited_response(Problem_t *p,char **a,int cnt,int *tried,int *log_char)
1234: {
1235: int can_answer;
1236: char tmp_str[MAX_BUFFER_SIZE];
1237: char *error=NULL;
1238:
1239: switch( capa_check_answers(p,a,cnt,&error) ) {
1240:
1241:
1242: case EXACT_ANS: *log_char='Y'; break;
1243: case APPROX_ANS: *log_char='Y'; break;
1244: case SIG_FAIL: *log_char='S'; capa_mfree(error); break;
1245: case UNIT_FAIL: *log_char='U'; capa_mfree(error); break;
1246: case UNIT_NOTNEEDED: *log_char='U'; capa_mfree(error); break;
1247: case NO_UNIT: *log_char='u'; break;
1248: case BAD_FORMULA:*log_char='F'; break;
1249: case INCORRECT: *log_char='N'; break;
1250: case WANTED_NUMERIC: *log_char='s'; break;
1251: case ANS_CNT_NOT_MATCH: *log_char='C'; break;
1252: }
1253:
1254: if(*tried < TRY_BOUND) (*tried)++;
1255: if ( *tried < p->tries ) {
1256: can_answer=YAK;
1257: if( (p->tries - *tried) == 1 ) {
1258: sprintf(tmp_str,"*Answered, ONE try left!! ");
1259: } else {
1260: sprintf(tmp_str,"*Answered, tries %2d/%2d ",*tried,p->tries);
1261: }
1262: } else {
1263: can_answer=NAY;
1264: sprintf(tmp_str, "*Answered, no more tries ");
1265: }
1266: move(S_ROW,S_COL); clrtoeol();
1267: mvaddstr(S_ROW,S_COL, tmp_str);
1268: return (can_answer);
1269: }
1270:
1271: int ask_what_prob(int q_cnt, char *ans)
1272: {
1273: int not_ok=1,num,anslength,i,j;
1274: char buf[5],buf2[MAX_BUFFER_SIZE];
1275:
1276: move(14,35); clrtoeol();
1277: move(17,5); clrtoeol();
1278: do {
1279: move(14,35); clrtoeol();
1280: move(15,0); clrtoeol();
1281: mvaddstr(15,13,"What problem number:");
1282: move(17,0); clrtoeol();
1283: mvaddstr(17,16," 1 2 3 4 5");
1284: mvaddstr(18,16,"12345678901234567890123456789012345678901234567890");
1285: anslength=strlen(ans);
1286: for(i=0;i<=(anslength/50);i++) {
1287: if ( g_inhibit_response ) {
1288: for(j=50*i;(j<((i+1)*50))&&(j<anslength);j++) {
1289: if (ans[j]=='-')
1290: buf2[j-(50*i)]='-';
1291: else
1292: buf2[j-(50*i)]='A';
1293: }
1294: buf2[j-(50*i)]='\0';
1295: } else {
1296: strncpy(buf2,&(ans[50*i]),50);
1297: }
1298: buf2[50]='\0';
1299: mvaddstr(19+i,16,buf2);
1300: if (anslength > 50 ) {
1301: sprintf(buf2,"%3d-%3d",i*50+1,(i+1)*50);
1302: mvaddstr(19+i,5,buf2);
1303: }
1304: }
1305: do { get_input(15,34,buf,4); } while(!strlen(buf));
1306: sscanf(buf,"%d",&num);
1307: if (num<1 || num>q_cnt) {
1308: move(21,5); clrtoeol();
1309: mvaddstr(21,15," Error: Invalid problem number\n");
1310: } else {
1311: not_ok = 0;
1312: }
1313: } while (not_ok);
1314:
1315: return (num);
1316: }
1317:
1318: /* gather subjective answers from student */
1319:
1320: #define BS 8
1321: #define DEL 127
1322: #define ESC 27
1323:
1324: #define COLON 58
1325:
1326: #define EDIT_HEIGHT 21
1327: #define EDIT_WIDTH 80
1328: #define MENULINE EDIT_HEIGHT
1329:
1330: void refresh_editor (char **sbuf_pp,int cx,int cy) {
1331: int i;
1332: CLEAR();
1333: echo();
1334: mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move curser");
1335: mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
1336: mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
1337: for(i=0;i<EDIT_HEIGHT;i++) { mvaddstr(i,0,sbuf_pp[i]); }
1338: move(cy,cx); refresh(); noecho();
1339: }
1340:
1341: void init_editor(char*** sbuf_pp)
1342: {
1343: int ww=EDIT_WIDTH, hh=EDIT_HEIGHT,i;
1344: *sbuf_pp = (char **)capa_malloc(sizeof(char *),hh);
1345: for(i=0;i<hh;i++) {
1346: (*sbuf_pp)[i] = (char *)capa_malloc(sizeof(char)*ww+1,1);
1347: }
1348: CLEAR();echo();
1349: mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move cursor");
1350: mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
1351: mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
1352: move(0,0); refresh(); noecho();
1353: }
1354:
1355: void remove_character(char** sbuf_pp,int *cx,int *cy)
1356: {
1357: int sx=(*cx)-1,sy=*cy;
1358: char temp,*temp_p;
1359: if (*cx==0) {
1360: int abovelen,curlen,diff,i,j;
1361: if (*cy==0) { beep();return;}
1362: abovelen=strlen(sbuf_pp[(*cy-1)]);
1363: curlen=strlen(sbuf_pp[*cy]);
1364: if (abovelen > 0) sbuf_pp[(*cy)-1][abovelen-1]='\0';
1365: if ((abovelen+curlen) < EDIT_WIDTH) {
1366: strcat(sbuf_pp[(*cy)-1],sbuf_pp[*cy]);
1367: memset(sbuf_pp[(*cy)],'\0',EDIT_WIDTH+1);
1368: temp_p=sbuf_pp[*cy];
1369: i=*cy;
1370: while(i<EDIT_HEIGHT-1) {
1371: sbuf_pp[i]=sbuf_pp[i+1];
1372: echo();move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);noecho();
1373: i++;
1374: }
1375: sbuf_pp[EDIT_HEIGHT-1]=temp_p;
1376: echo();move(EDIT_HEIGHT-1,0);CLRTOEOL();noecho();
1377: } else {
1378: diff=EDIT_WIDTH-abovelen;
1379: strncat(sbuf_pp[(*cy)-1],sbuf_pp[*cy],diff);
1380: i=diff;j=0;
1381: while(sbuf_pp[*cy][i]!='\0') {
1382: sbuf_pp[*cy][j]=sbuf_pp[*cy][i];
1383: i++;j++;
1384: }
1385: memset(&(sbuf_pp[(*cy)][j]),'\0',EDIT_WIDTH+1-j);
1386: }
1387: echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
1388: (*cy)--;
1389: echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
1390: if ( EDIT_WIDTH == ((*cx)=(abovelen-1))) (*cx)--;
1391: if (abovelen==0) *cx=0;
1392: echo();move(*cy,*cx);noecho();
1393: } else {
1394: echo();move(sy,sx);noecho();
1395: temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
1396: sx++;
1397: while(temp!='\0') {
1398: echo(); ADDCH(temp); noecho();
1399: temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
1400: sx++;
1401: }
1402: echo(); ADDCH(' '); noecho();
1403: (*cx)--;
1404: }
1405: echo();move(*cy,*cx);noecho();
1406: }
1407:
1408: void break_line (char** sbuf_pp,int *cx,int *cy)
1409: {
1410: int sx=*cx,sy=*cy,i;
1411: if (sy < EDIT_HEIGHT-1) {
1412: capa_mfree(sbuf_pp[EDIT_HEIGHT-1]);
1413: i=EDIT_HEIGHT-1;
1414: while (i-1 > sy) {
1415: sbuf_pp[i]=sbuf_pp[i-1];
1416: move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);
1417: i--;
1418: }
1419: sbuf_pp[sy+1]=capa_malloc(sizeof(char)*EDIT_WIDTH+1,1);
1420: }
1421: strcat(sbuf_pp[sy+1],&(sbuf_pp[sy][sx]));
1422: memset(&(sbuf_pp[sy][sx]),'\0',EDIT_WIDTH+1-sx);
1423: *cx=0;
1424: (*cy)++;
1425: move(sy,0);CLRTOEOL();mvaddstr(sy,0,sbuf_pp[sy]);
1426: move(sy+1,0);CLRTOEOL();mvaddstr(sy+1,0,sbuf_pp[sy+1]);
1427: }
1428:
1429: /* FIXME catch funtion keys and others? */
1430: void handle_esc (unsigned char ca,unsigned char cb,char** sbuf_pp,int *cx,int *cy)
1431: {
1432: if( ca!='[') return;
1433: switch (cb) {
1434: case 'A':/* KEY_UP */
1435: if(*cy>0){
1436: (*cy)--;
1437: while(*cx>0 && sbuf_pp[*cy][(*cx)-1]=='\0') (*cx)--; /* goto end of line */
1438: } else {
1439: beep();
1440: }
1441: break;
1442: case 'B': /* KEY_DOWN */
1443: if (*cy<(EDIT_HEIGHT-1)) {
1444: (*cy)++;
1445: while(*cx>0 && sbuf_pp[*cy][(*cx)-1]=='\0') (*cx)--; /* goto end of line */
1446: } else {
1447: beep();
1448: }
1449: break;
1450: case 'C': /* KEY_RIGHT */
1451: if ( *cx<(EDIT_WIDTH-1) && sbuf_pp[*cy][(*cx)]!='\0' ) {
1452: (*cx)++;
1453: } else {
1454: if (*cy<(EDIT_HEIGHT-1)) {
1455: (*cy)++; *cx=0;
1456: } else {
1457: beep();
1458: }
1459: }
1460: break;
1461: case 'D': /* KEY_LEFT */
1462: if(*cx>0) {
1463: (*cx)--;
1464: } else {
1465: if(*cy>0) {
1466: (*cy)--;
1467: *cx=strlen(sbuf_pp[*cy]);
1468: if (*cx==EDIT_WIDTH) (*cx)--;
1469: } else {
1470: beep();
1471: }
1472: }
1473: break;
1474: default: beep(); return; break;
1475: }
1476: echo(); move(*cy,*cx); refresh(); noecho();
1477: }
1478:
1479: void handle_error (unsigned char c,char** sbuf_pp,int cx,int cy)
1480: {
1481: beep();
1482: }
1483:
1484: /*FIXME Slower than whale shit*/
1485: void insert_character(unsigned char c,char** sbuf_pp,int *cx,int *cy)
1486: {
1487: int sx=*cx,sy=*cy;
1488: unsigned char temp;
1489: while(c!='\0') {
1490: if (sx == EDIT_WIDTH) {
1491: sx=0;sy++;
1492: if (sy == EDIT_HEIGHT) {
1493: sy--;sx=EDIT_WIDTH;c='\0';break;
1494: }
1495: }
1496: echo(); ADDCH(c); noecho();
1497: temp=sbuf_pp[sy][sx];
1498: sbuf_pp[sy][sx]=c;
1499: c=temp;
1500: sx++;
1501: }
1502: sbuf_pp[sy][sx]=c;
1503: (*cx)++;
1504: if (*cx == EDIT_WIDTH) {
1505: *cx=0;(*cy)++;
1506: if (*cy == EDIT_HEIGHT) {
1507: (*cy)--;*cx=EDIT_WIDTH-1;
1508: }
1509: }
1510: move(*cy,*cx);refresh();
1511: }
1512:
1513: int handle_keystrokes_editor(char** sbuf_pp)
1514: {
1515: int done = 0, forget = 0, cx=0,cy=0;
1516: unsigned char c,ca,cb;
1517:
1518: while (!done) {
1519: move(cy,cx);refresh();
1520: c=getch();
1521: switch(c) {
1522: case BS: case DEL:
1523: remove_character(sbuf_pp,&cx,&cy);
1524: break;
1525: case CR: case LF:
1526: break_line(sbuf_pp,&cx,&cy);
1527: break;
1528: case ESC:
1529: ca=getch();cb=getch();
1530: handle_esc(ca,cb,sbuf_pp,&cx,&cy);
1531: break;
1532: case 5: /*ctrl-e*/
1533: done=1;
1534: break;
1535: case 6: /*ctrl-f*/
1536: done=1;
1537: forget=1;
1538: break;
1539: case 12:
1540: refresh_editor(sbuf_pp,cx,cy);
1541: break;
1542: default:
1543: if (c < 32 || c>126) {
1544: handle_error(c,sbuf_pp,cx,cy);
1545: } else {
1546: insert_character(c,sbuf_pp,&cx,&cy);
1547: }
1548: break;
1549: }
1550: }
1551: return forget;
1552: }
1553:
1554: int editor(char*** sbuf_pp)
1555: {
1556: init_editor(sbuf_pp);
1557: return handle_keystrokes_editor(*sbuf_pp);
1558: }
1559:
1560:
1561: int
1562: answer_subjective(student_number,set,section,prob)
1563: char *student_number;
1564: int set;
1565: int *section;
1566: int prob;
1567: {
1568: int i,length;
1569: char date_str[DATE_LENGTH];
1570: char **sbuf_pp,answer[(EDIT_HEIGHT*(EDIT_WIDTH+1))+1];
1571: char submissions_str[(EDIT_HEIGHT*(EDIT_WIDTH+1))+MAX_BUFFER_SIZE];
1572: time_t curtime;
1573:
1574: time(&curtime);
1575: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1576: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1577: sprintf(answer,"Sorry, the due date was: %s",date_str);
1578: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1579: return 0;
1580: }
1581:
1582: if (editor(&sbuf_pp)) { return 0; }
1583:
1584: answer[0]='\0';
1585: for(i=0;i<EDIT_HEIGHT;i++) {
1586: if (strlen(sbuf_pp[i]) > 0) {
1587: strcat(answer,sbuf_pp[i]);
1588: length=strlen(answer);
1589: answer[length]='\n';
1590: answer[length+1]='\0';
1591: }
1592: capa_mfree((char *)sbuf_pp[i]);
1593: }
1594: capa_set_subjective(set,prob,student_number,answer);
1595: sprintf(submissions_str,"%d\t%s\t",prob,answer);
1596: log_submissions(student_number,set,submissions_str);
1597: capa_mfree((char *)sbuf_pp);
1598: return 1;
1599: }
1600:
1601: void set_entry_tries(int *tried, char *tries, int num, int num_questions) {
1602: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1603: if(tried[num] < 10 ) {
1604: tries[3*num] = ' ';
1605: tries[3*num+1] = tried[num] + '0';
1606: if(num < num_questions-1) tries[3*num+2] = ',';
1607: } else {
1608: tries[3*num] = (int)(tried[num]/10) + '0';
1609: tries[3*num+1] = (tried[num] % 10) + '0';
1610: if(num < num_questions-1) tries[3*num+2] = ',';
1611: }
1612: } else {
1613: tries[3*num] = ' ';
1614: tries[3*num+1] = 1 + '0';
1615: if(num < num_questions-1) tries[3*num+2] = ',';
1616: }
1617: }
1618:
1619: /* -------------------------------------------------------------------------- */
1620: /* LET THE USER ANSWER THE CURRENT PROBLEM SET QUESTIONS */
1621: /* -------------------------------------------------------------------------- */
1622: void
1623: try_set(student_number,set,section)
1624: char *student_number;
1625: int set;
1626: int *section;
1627: {
1628: char a_student_number[MAX_STUDENT_NUMBER+1];
1629: time_t curtime;
1630: T_header header;
1631: Problem_t *first_problem, *p;
1632: T_entry entry;
1633: char answer[256], *a_str, **ans_strs;
1634: int num, offset, num_questions, start_from, leng;
1635: char *log_string,submissions_str[MAX_BUFFER_SIZE];
1636: int *tried,answered;
1637: int scr_idx=1, display=1, second_scr, canAnswer;
1638: int usr_command, whereto, allow_hint=0, ex=0;
1639: char u_input[64], date_str[DATE_LENGTH], one_line[81];
1640: int log_char, i, j, allow_n, allow_p, allow_subj;
1641:
1642: strncpy(a_student_number,student_number,MAX_STUDENT_NUMBER+1);
1643: time(&curtime); /* Is due date past? */
1644: /* ---------------------------------------- check due date */
1645: #ifndef NO_DATE_CHECK
1646: /* ===> if ( compare_datetime(curtime,header.due_date) > 0) { */
1647: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1648: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1649: sprintf(answer," Sorry, the due date was: %s",date_str);
1650: move(17,1); clrtoeol(); mvaddstr(17,15,answer); mypause(19,17);
1651: return;
1652: }
1653: #ifdef LOGIN_DBUG
1654: fprintf(dfp,"Tryset():(sec=%d,set=%d)[%s]\n",*section,set,date_str); fflush(dfp);
1655: #endif /* LOGIN_DBUG */
1656: #endif /* NO_DATE_CHECK */
1657:
1658: offset=capa_get_entry(&entry,student_number,set);
1659: capa_get_header(&header,set);
1660: if (offset<0) offset = -offset; /* newly created entry */
1661:
1662: #ifdef LOGIN_DBUG
1663: fprintf(dfp,"P set=%d,SN=%s,ANS=%s,TRY=%s\n",set,a_student_number,entry.answers,entry.tries); fflush(dfp);
1664: #endif
1665: num = capa_parse(set,&first_problem,a_student_number,&num_questions,NULL);
1666:
1667: #ifdef LOGIN_DBUG
1668: fprintf(dfp,"ParseSource:=%d\n",num); fflush(dfp);
1669: #endif /* LOGIN_DBUG */
1670:
1671: /* DEBUGGING: make sure num_questions is plausible */
1672: if (num_questions>1000 || num_questions<=0) properly_logout(student_number);
1673:
1674: start_from=ask_what_prob(num_questions,entry.answers);
1675:
1676: /* initialize log string to all '-' */
1677: tried = (int *)capa_malloc(num_questions+1,sizeof(int));
1678: log_string = (char *)capa_malloc(num_questions+1,sizeof(char));
1679: for (num=0; num<num_questions; num++) {
1680: log_string[num]='-';
1681: sscanf(entry.tries + 3*num,"%d,",&(tried[num]) );
1682: }
1683: log_string[num_questions]=0;
1684: capa_set_login_time(student_number,set);
1685: for (num=0,p=first_problem; p; ){
1686: if( start_from > 1 ) {
1687: num=start_from-1;
1688: for (p=first_problem; start_from > 1 && p->next; start_from--)
1689: p=p->next;
1690: start_from = 0;
1691: }
1692: if (display) {
1693: /* DISPLAY QUESTION */
1694: CLEAR();
1695: second_scr = display_prob_scr(p->question,scr_idx);
1696: allow_subj = 0;
1697: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
1698: allow_subj = 1;
1699: move(A_ROW,A_COL); clrtoeol();
1700: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1701: }
1702: mvaddstr(S_ROW,0,"OPTION/ANSWER");
1703: mvaddstr(O_ROW,0,"Options :M = Main Menu :7 = go to # 7");
1704: allow_n = allow_p = 0;
1705: if( second_scr && (scr_idx == 1) ) {
1706: mvaddstr(O_ROW,E_COL,":N = Next screen");
1707: allow_n=1;
1708: }
1709: if( second_scr && (scr_idx == 2) ) {
1710: mvaddstr(O_ROW,E_COL,":P = Prev screen");
1711: allow_p=1;
1712: }
1713:
1714: mvaddstr(O_ROW,R_COL,"RETURN = Enter/Execute");
1715:
1716: if (g_inhibit_response ) {
1717: canAnswer = show_prior_inhibited_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1718: } else {
1719: canAnswer = show_prior_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1720: }
1721:
1722: }
1723: mvaddstr(X_ROW,X_COL,":X = eXit");
1724:
1725: /* <= */
1726:
1727:
1728:
1729: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1730: display=0; usr_command=C_DONTCARE;
1731: /* DEFAULT ACTIONS on empty input */
1732: if(!strlen(u_input)) { usr_command = (p->next? C_FORWARD : C_MENU); } else {
1733: if( u_input[0] == ':' ) {
1734: switch(toupper( u_input[1] )) {
1735: case 'H': if( allow_hint ) { usr_command=C_HINT; } break;
1736: case 'M': usr_command=C_MENU; break;
1737: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
1738: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
1739: case 'X': usr_command=C_EXIT; break;
1740: case 'A': if( allow_subj ) { usr_command=C_SUBJANS; } break;
1741: default : sscanf(u_input,":%d",&whereto);
1742: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
1743: break;
1744: }
1745: } else { /* user entered some answer */
1746: if( p->ans_op == ANS_AND ) {
1747: if(canAnswer) { usr_command=C_ANSWER;
1748: ans_strs = (char **)capa_malloc(sizeof(char *), p->ans_cnt);
1749: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1750: strcpy(ans_strs[0],u_input);
1751: for(i=1;i<p->ans_cnt;i++) {
1752: mvaddstr(A_ROW,A_COL," ");
1753: mvaddstr(A_ROW,A_COL,ans_strs[i-1]);
1754: sprintf(one_line, " Entering answer %3d of %3d ", i+1,p->ans_cnt);
1755: mvaddstr(A_ROW,S_COL,one_line);
1756: mvaddstr(S_ROW,A_COL," ");
1757: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1758: ans_strs[i] = (char *)capa_malloc(strlen(u_input)+1,1);
1759: strcpy(ans_strs[i],u_input);
1760:
1761: }
1762:
1763: /* now in ans_strs[][] are user inputs */
1764:
1765: }
1766: } else { /* one answer or ANS_OR */
1767: ans_strs = (char **)capa_malloc(sizeof(char *), 1);
1768: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1769: strcpy(ans_strs[0], u_input);
1770: if(canAnswer) { usr_command=C_ANSWER;
1771: mvaddstr(S_ROW,A_COL," ");
1772: mvaddstr(A_ROW,A_COL," ");
1773: mvaddstr(A_ROW,A_COL,ans_strs[0]); }
1774: }
1775: } /* end if u_input[0] == ':' */
1776: } /* end if !strlen(u_input) */
1777:
1778:
1779:
1780:
1781:
1782: /* PROCESS USER COMMAND */
1783: switch(usr_command) {
1784: case C_FORWARD: /* Forwards */
1785: if (p->next) {
1786: p=p->next; num++;
1787: display=1; allow_hint=0; scr_idx=1;
1788: } else
1789: mvaddstr(X_ROW,R_COL,"RETURN = Main Menu ");
1790: break;
1791: case C_NEXTSCR: scr_idx = 2; display=1;
1792: break;
1793: case C_PREVSCR: scr_idx = 1; display=1;
1794: break;
1795: case C_EXIT: /* Exit */
1796: ex=1; p=0; break;
1797: case C_MENU: /* Return to main menu */
1798: p=0; break;
1799: case C_HINT: /* Hint */
1800: if (! p->hint) break;
1801: display_hint(p->hint);
1802: display=1;
1803: break;
1804: case C_ANSWER: /* Answer question */
1805: {
1806: if(p->ans_type== ANSWER_IS_SUBJECTIVE) {
1807: move(A_ROW,A_COL); clrtoeol();
1808: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1809: capa_mfree(ans_strs[0]);
1810: break;
1811: }
1812: if( p->ans_op == ANS_AND ) {
1813: leng = 0;
1814: for(i=0;i<p->ans_cnt;i++) {
1815: leng += (strlen((char *)ans_strs[i]) + 2);
1816: }
1817: a_str = (char *)capa_malloc(leng+1,1);
1818: a_str[0]=0;
1819: strcat(a_str,ans_strs[0]);
1820: if ( is_all_ws(ans_strs[0]) ) break;
1821: trim_response_ws(ans_strs[0]);
1822: for(i=1;i<p->ans_cnt;i++) {
1823: strcat(a_str,"\t");
1824: strcat(a_str,ans_strs[i]);
1825: if ( is_all_ws(ans_strs[i]) ) break;
1826: trim_response_ws(ans_strs[i]);
1827: }
1828: if (i < p->ans_cnt) {
1829: display=1; /*handle early breaks out of the*/
1830: break; /*loop which mean typed only ws */
1831: }
1832: } else { /* only one answer */
1833: leng = (strlen((char *)ans_strs[0]) + 2);
1834: a_str = (char *)capa_malloc(leng+1,1);
1835: a_str[0]=0;
1836: strcat(a_str,ans_strs[0]);
1837: if ( is_all_ws(ans_strs[0]) ) break;
1838: trim_response_ws(ans_strs[0]);
1839: }
1840:
1841: sprintf(submissions_str,"%d\t%s\t",num+1,a_str);
1842: log_submissions(student_number,set,submissions_str);
1843:
1844: {
1845: int cnt=((p->ans_op==ANS_AND)?p->ans_cnt:1);
1846: if (g_inhibit_response) {
1847: canAnswer = give_inhibited_response(p, ans_strs,cnt,
1848: &(tried[num]),&log_char);
1849: } else {
1850: canAnswer = give_response(p, ans_strs,cnt, &(tried[num]),&log_char);
1851: }
1852: }
1853: if( p->ans_op == ANS_AND ) {
1854: for(i=0;i<p->ans_cnt;i++) {
1855: capa_mfree( (char *)ans_strs[i] );
1856: }
1857:
1858: } else { /* there is only one user answer */
1859: capa_mfree( (char *)ans_strs[0] );
1860:
1861: }
1862: capa_mfree((char *)ans_strs);
1863: capa_mfree( (char *)a_str );
1864:
1865: if (p->hint &&
1866: (
1867: (p->show_hint<=tried[num])||
1868: (log_char == 'y') ||
1869: (log_char == 'Y')
1870: )
1871: ){
1872: allow_hint=1;
1873: mvaddstr(X_ROW,H_COL,":H = Show Hint");
1874: }
1875: switch(log_char) {
1876: case 'U': case 'u': case 'S': case 'F':
1877: entry.answers[num]='N'; break;
1878: case 'Y': allow_hint=1; mvaddstr(X_ROW,H_COL,":H = Show Hint"); /* fall through here */
1879: default: entry.answers[num]=log_char; break;
1880: }
1881: log_string[num]=log_char;
1882:
1883: log_attempt(student_number,set,*section,log_string);
1884: /* for (i=0; i<num_questions; i++) { log_string[i] = '-' ; } */
1885: set_entry_tries(tried,entry.tries,num,num_questions);
1886: log_string[num]='-';
1887: /* ------------------------------ check due date */
1888: time(&curtime);
1889: /* ===> if (compare_datetime(curtime,header.due_date) > 0) { */
1890: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1891: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1892: sprintf(answer,"Sorry, the due date was: %s",date_str);
1893: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1894: } else {
1895: capa_set_entry(&entry,student_number,set,offset);
1896: }
1897: } break;
1898: case C_JUMP: /* Jump to specific question number */
1899: num=whereto-1;
1900: for (p=first_problem; whereto > 1 && p->next; whereto--)
1901: p=p->next;
1902: display=1; allow_hint=0; scr_idx=1;
1903: break;
1904: case C_SUBJANS:
1905: answered=answer_subjective(student_number,set,section,num+1);
1906: if (answered) {
1907: tried[num]++;
1908: if (p->hint && ((p->show_hint<=tried[num]))) { allow_hint=1; }
1909: entry.answers[num]='0';
1910: log_string[num]='A';
1911: log_attempt(student_number,set,*section,log_string);
1912: log_string[num]='-';
1913: set_entry_tries(tried,entry.tries,num,num_questions);
1914: capa_set_entry(&entry,student_number,set,offset);
1915: }
1916: display=1;
1917: break;
1918: case C_DONTCARE: break;
1919: }
1920: }
1921: for (i=0,j=0, num=0; num<num_questions; num++) {
1922: j = j + (header.weight[num] - '0');
1923: if((entry.answers[num]=='Y') || (entry.answers[num]=='y'))
1924: i = i + (header.weight[num] - '0');
1925: if( entry.answers[num] >= '0' && entry.answers[num] <= '9' ) {
1926: i = i + (entry.answers[num] - '0');
1927: }
1928: if((entry.answers[num]=='E') || (entry.answers[num]=='e'))
1929: j = j - (header.weight[num] - '0');
1930: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1931: if(tried[num] < 10 ) {
1932: entry.tries[3*num] = ' ';
1933: entry.tries[3*num+1] = tried[num] + '0';
1934: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1935: } else {
1936: entry.tries[3*num] = (int)(tried[num]/10) + '0';
1937: entry.tries[3*num+1] = (tried[num] % 10) + '0';
1938: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1939: }
1940: } else {
1941: entry.tries[3*num] = ' ';
1942: entry.tries[3*num+1] = 1 + '0';
1943: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1944: }
1945: }
1946: capa_mfree(header.weight);
1947: capa_mfree(header.partial_credit);
1948:
1949: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1950: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1951: /* ------- original code , should check due date before save it
1952:
1953: time(&curtime);
1954: if (compare_datetime(curtime,header.due_date) > 0) {
1955: if( capa_check_date(CHECK_DUE_DATE,*section,set) > 0 ) {
1956: need to deal with due_date
1957: sprintf(answer,"Sorry, the due date was: %s",header.due_date);
1958: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1959: } else {
1960: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1961: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1962:
1963: capa_set_entry(&entry,student_number,set,offset);
1964: }
1965: ------ */
1966: /* FREE UP MALLOC'ED SPACE (VERY IMPORTANT) */
1967: capa_mfree(entry.answers);
1968: capa_mfree(entry.tries);
1969: free_problems(first_problem);
1970: /* log_attempt(student_number,set,*section,log_string); */
1971: capa_mfree(log_string);
1972: capa_mfree((char*)tried);
1973: if (ex) properly_logout(student_number);
1974:
1975: }
1976:
1977: #define COL_ONE 1
1978: #define COL_TWO 17
1979: #define COL_THREE 34
1980: #define COL_FOUR 43
1981: #define COL_FIVE 69
1982:
1983: /* ------------------------------------------------------------------------- */
1984: /* REVIEW PREVIOUS PROBLEM SETS */
1985: /* ------------------------------------------------------------------------- */
1986: void /* RETURNS: (nothing) */
1987: view_previous(student_number,set,section) /* ARGUMENTS: */
1988: char *student_number; /* Student number */
1989: int set; /* Set number */
1990: int *section; /* Section number */
1991: { /* LOCAL VARIABLES: */
1992: T_entry entry; /* Database entry */
1993: Problem_t *first_problem, /* Pointer to first problem */
1994: *problem; /* Previous problem */
1995: int num_questions, /* Total # of questions */
1996: ex=0, /* Exit system flag */
1997: display=1, /* Redraw flag */
1998: usr_command,
1999: whereto,
2000: allow_hint=0, allow_explain=0;
2001: int num; /* Temporary variable */
2002: char buf[4], /* Command input buffer */
2003: aLine[MAX_BUFFER_SIZE];
2004: T_header header; /* Set header */
2005: time_t curtime; /* Current time */
2006: double upper_ans;
2007: char fmt_ans[ANSWER_STRING_LENG], goto_str[ANSWER_STRING_LENG],
2008: tmp_str[ANSWER_STRING_LENG];
2009: int scr_idx=1, second_scr, allow_n, allow_p;
2010:
2011: /* QUERY USER FOR SET */
2012: move(15,5); /* deleteln(); */
2013: addstr(" Which set would you like to view?");
2014: mvaddstr(16,15, "Enter a set number and press ENTER/RETURN");
2015: move(17,1); clrtoeol(); /* erase Enter a command ... */
2016: do { get_input(15,51,buf,3); } while(!strlen(buf));
2017: sscanf(buf,"%d",&num);
2018: if (num<1 || num>set) {
2019: move(17,5); clrtoeol();
2020: mvaddstr(17,15," Error: Invalid previous set number\n");
2021: mypause(19,17); return;
2022: }
2023: /* ------------------------------------ answer date */
2024: time(&curtime);
2025: /* ===> if (compare_datetime(curtime,header.answer_date) < 0) { */
2026: if ( capa_check_date(CHECK_ANS_DATE,student_number,*section,num) < 0 ) {
2027: move(16,1); clrtoeol();
2028: move(17,5); clrtoeol();
2029: mvaddstr(17,15," Answers are not yet available\n"); mypause(19,17); return;
2030: }
2031:
2032: /* LOAD IN THE INFO NEEDED */
2033: capa_get_header(&header,num);
2034: capa_get_entry(&entry,student_number,num);
2035: capa_parse(num,&first_problem,student_number,&num_questions,NULL);
2036: sprintf(goto_str,"#=go to problem #, [%d problems]", num_questions);
2037: for (num=0,problem=first_problem; problem; ) {
2038: if (display) {
2039: allow_hint = allow_explain=0;
2040: allow_n = allow_p = 0;
2041: CLEAR();
2042: second_scr = display_prob_scr(problem->question,scr_idx);
2043: if( problem->ans_type == ANSWER_IS_FLOAT ) {
2044: upper_ans = (double)atof(problem->answer);
2045: sprintf(fmt_ans, problem->ans_fmt, upper_ans);
2046: } else {
2047: sprintf(fmt_ans, "%s", problem->answer);
2048: }
2049: if( problem->ans_unit ) {
2050: sprintf(tmp_str, "Answer: %s %s",fmt_ans,problem->unit_str);
2051: } else {
2052: sprintf(tmp_str, "Answer: %s",fmt_ans);
2053: }
2054: mvaddstr(S_ROW,COL_ONE,tmp_str);
2055:
2056: switch(entry.answers[num]) {
2057: case 'Y': mvaddstr(S_ROW,COL_FOUR,"CORRECT "); break;
2058: case 'y': mvaddstr(S_ROW,COL_FOUR,"HANDIN CORRECT "); break;
2059: case '-': mvaddstr(S_ROW,COL_FOUR,"UNANSWERED "); break;
2060: case 'e': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2061: case 'E': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2062: case 'n': mvaddstr(S_ROW,COL_FOUR,"HANDIN INCORRECT"); break;
2063: case 'N': mvaddstr(S_ROW,COL_FOUR,"INCORRECT "); break;
2064: default : if(entry.answers[num] >= '0' && entry.answers[num] <= '9') {
2065: sprintf(aLine,"HAND-GRADED %c/%c ",entry.answers[num],
2066: header.weight[num]);
2067: mvaddstr(S_ROW,COL_FOUR,aLine);
2068: }
2069: break;
2070: }
2071: mvaddstr(S_ROW,COL_FIVE,"OPTION:");
2072:
2073: mvaddstr(O_ROW,COL_ONE,"M=Main menu");
2074: if( second_scr && scr_idx == 1) {
2075: mvaddstr(O_ROW,COL_TWO,"N=Next screen");
2076: allow_n = 1;
2077: }
2078: if( second_scr && scr_idx == 2) {
2079: mvaddstr(O_ROW,COL_TWO,"P=Prev screen");
2080: allow_p = 1;
2081: }
2082: mvaddstr(O_ROW,COL_THREE,"X=eXit");
2083: mvaddstr(O_ROW,COL_FOUR, "RETURN=Enter/Execute");
2084: if ( problem->hint &&
2085: (
2086: (problem->show_hint <= problem->tries) ||
2087: (entry.answers[num] == 'Y') ||
2088: (entry.answers[num] == 'y')
2089: )
2090: ) {
2091: allow_hint=1; mvaddstr(O_ROW,COL_FIVE,"H=Hint");
2092: }
2093: mvaddstr(X_ROW,COL_ONE,goto_str);
2094: if (problem->next)
2095: mvaddstr(X_ROW,COL_FOUR,"RETURN=next problem");
2096: else
2097: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2098: if ( problem->explain ) { allow_explain=1; mvaddstr(X_ROW,COL_FIVE,"E=Explain"); }
2099:
2100: }
2101: get_input(S_ROW,COL_FIVE+7,buf,3);
2102: display=0; usr_command=C_DONTCARE;
2103: /* DEFAULT ACTIONS on empty input */
2104: if(!strlen(buf)) { usr_command = (problem->next? C_FORWARD : C_MENU); } else {
2105: switch(toupper(buf[0])) {
2106: case 'X': usr_command=C_EXIT; break;
2107: case 'M': usr_command=C_MENU; break;
2108: case 'H': usr_command=C_HINT; break;
2109: case 'E': usr_command=C_EXPLAIN; break;
2110: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
2111: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
2112: default : sscanf(buf,"%d",&whereto);
2113: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
2114: break;
2115: }
2116: }
2117:
2118:
2119: /* PROCESS USER COMMAND */
2120: switch(usr_command) {
2121: case C_FORWARD: /* FORWARDS ONE */
2122: if (problem->next) {
2123: problem=problem->next; display=1; scr_idx = 1; num++;
2124: } else
2125: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2126: break;
2127: case C_HINT: /* HINT */
2128: if(allow_hint) {
2129: display_hint(problem->hint);
2130: display=1;
2131: allow_hint = 0;
2132: }
2133: break;
2134: case C_EXPLAIN: /* Explain */
2135: if(allow_explain) {
2136: display_hint(problem->explain); display=1;
2137: allow_explain=0;
2138: }
2139: break;
2140: case C_NEXTSCR: scr_idx = 2; display=1;
2141: break;
2142: case C_PREVSCR: scr_idx = 1; display=1;
2143: break;
2144: case C_EXIT: /* EXIT SYSTEM */
2145: ex=1; problem=0; break;
2146:
2147: case C_MENU: /* RETURN TO MAIN MENU */
2148: problem=0; break;
2149:
2150: case C_JUMP: /* JUMP TO SPECIFIC PROBLEM # */
2151: num=whereto-1;
2152: for (problem=first_problem; whereto > 1 && problem->next; whereto--)
2153: problem=problem->next;
2154: display=1;
2155: scr_idx = 1;
2156: break;
2157: case C_TIME: break;
2158: case C_DONTCARE: break;
2159: }
2160: }
2161:
2162: /* FREE UP MALLOC'ED SPACE - VERY IMPORTANT */
2163: capa_mfree(header.weight);
2164: capa_mfree(header.partial_credit);
2165: capa_mfree(entry.answers);
2166: capa_mfree(entry.tries);
2167: free_problems(first_problem);
2168:
2169: if (ex) properly_logout(student_number);
2170: }
2171:
2172: /* -------------------------------------------------------------------------- */
2173: /* DISPLAY HELP SCREEN */
2174: /* -------------------------------------------------------------------------- */
2175: void /* RETURNS: (nothing) */
2176: display_help() /* ARGUMENTS: (none) */
2177: { /* LOCAL VARIABLES: */
2178: FILE *fp; /* Welcome file pointer */
2179: char buf[255]; /* Input buffer */
2180:
2181: CLEAR();
2182: if ((fp=fopen("help.msg","r"))!=NULL) {
2183: while (fgets(buf,255,fp)) addstr(buf);
2184: fclose(fp);
2185: }
2186: mypause(22,20);
2187: }
2188:
2189:
2190: /* A class directory must have */
2191: /* records/ */
2192: /* */
2193: /* returns: 0 structure is correct, but no set.db files */
2194: /* -1 structure is not correct */
2195: /* >=1 the last set.db */
2196:
2197: int
2198: check_class_get_set(dir_path) char *dir_path;
2199: {
2200: char f_name[1024];
2201: int set;
2202:
2203: if( capa_access(dir_path, F_OK) == 0 ) { /* class dir exists */
2204: sprintf(f_name,"%s/records",dir_path);
2205: if( capa_access(f_name, F_OK) == 0 ) { /* class/records dir exists */
2206: for(set = 1; ; set++ ) {
2207: sprintf(f_name,"%s/records/set%d.db",dir_path,set);
2208: if(capa_access(f_name, F_OK) == -1 ) break;
2209: }
2210: set--;
2211: } else {
2212: set = -1;
2213: }
2214: } else {
2215: set = -1;
2216: }
2217: return (set);
2218: }
2219: /* -------------------------------------------------------------------------- */
2220: /* Get Exam and Quiz Path */
2221: /* return 0, 1, 2, 3 */
2222: /* -------------------------------------------------------------------------- */
2223: int
2224: check_exam_quiz_f()
2225: {
2226: char buf[MAX_BUFFER_SIZE];
2227: int result = 0, configResult=0;
2228:
2229: #ifdef LOGIN_DBUG
2230: fprintf(dfp,"CHECK EXAM Access() success,and open(),%s\n",buf); fflush(dfp);
2231: #endif
2232: configResult=read_capa_config("exam_path",buf);
2233: if (configResult != 0 && configResult != -1) {
2234: Exam_set = check_class_get_set(buf);
2235: if(Exam_set > 0 ) {
2236: result = 1;
2237: sprintf(Exam_path,buf);
2238: }
2239: }
2240: #ifdef LOGIN_DBUG
2241: fprintf(dfp,"CHECK EXAM = %d,%s\n", result,Exam_path); fflush(dfp);
2242: #endif
2243: configResult=read_capa_config("quiz_path",buf);
2244: if (configResult != 0 && configResult != -1) {
2245: Quiz_set = check_class_get_set(buf);
2246: if(Quiz_set > 0 ) {
2247: result = (result | 2);
2248: sprintf(Quiz_path,buf);
2249: }
2250: }
2251:
2252: return (result);
2253: }
2254:
2255: /* -------------------------------------------------------------------------- */
2256: /* DISPLAY MAIN MENU */
2257: /* -------------------------------------------------------------------------- */
2258: void /* RETURNS: (nothing) */
2259: display_menu(student, exam_f, quiz_f)
2260: T_student *student;
2261: int exam_f, quiz_f;
2262: {
2263: char buff[MAX_BUFFER_SIZE];
2264: int c_y,configResult,term_summary_button=1;
2265:
2266: configResult=read_capa_config("term_summary_button",buff);
2267: if (configResult != 0 && configResult != -1 ) {
2268: if (strcasecmp(buff,"no")==0) {
2269: term_summary_button=0;
2270: }
2271: }
2272:
2273: CLEAR();
2274:
2275: mvaddstr(1,10,student->s_nm);
2276: sprintf(buff,"Section: %d",student->s_sec);
2277: mvaddstr(1,50,buff);
2278:
2279: mvaddstr( 4,25," MAIN MENU"); c_y = 6;
2280: mvaddstr( c_y,25,"H=Help"); c_y++;
2281: if (term_summary_button) { mvaddstr( c_y,25,"S=Summary"); c_y++; }
2282: mvaddstr( c_y,25,"T=Try set"); c_y++;
2283: mvaddstr( c_y,25,"V=View previous set"); c_y++;
2284: if(exam_f) { mvaddstr( c_y,25,"E=view Exam summary"); c_y++; }
2285: if(quiz_f) { mvaddstr( c_y,25,"Q=view Quiz summary"); c_y++; }
2286: mvaddstr( c_y,25,"X=eXit system");
2287:
2288: mvaddstr(14,25,"COMMAND:");
2289:
2290: mvaddstr(17, 5,"Enter a command from the list above and press ENTER/RETURN");
2291: }
2292:
2293: /* -------------------------------------------------------------------------- */
2294: /* CONTROL MAIN MENU SELECTIONS */
2295: /* -------------------------------------------------------------------------- */
2296: void /* RETURNS: (nothing) */
2297: menu_main(student_number,set,section) /* ARGUMENTS: */
2298: char *student_number; /* Student number */
2299: int set; /* Set number */
2300: int section; /* Section number */
2301: { /* LOCAL VARIABLES: */
2302: int ex=0, /* Exit system flag */
2303: cmd; /* User command */
2304: char buff[MAX_BUFFER_SIZE]; /* User command buffer */
2305: T_student a_student;
2306: int had_exam, had_quiz, outcome,configResult;
2307:
2308: #ifdef LOGIN_DBUG
2309: fprintf(dfp,"MENU in %s sec=%d\n", student_number,section); fflush(dfp);
2310: #endif
2311:
2312: outcome = check_exam_quiz_f();
2313: had_exam = outcome & 1;
2314: had_quiz = outcome & 2;
2315:
2316: #ifdef LOGIN_DBUG
2317: fprintf(dfp,"After check %d\n", outcome); fflush(dfp);
2318: #endif
2319:
2320: capa_get_student(student_number,&a_student);
2321:
2322: g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set,section);
2323: if (g_inhibit_response < 0 ) g_inhibit_response=0;
2324:
2325: display_menu(&a_student,had_exam, had_quiz);
2326: while (!ex) {
2327: do {
2328: buff[0] = ' '; buff[1] = 0;
2329: get_input(14,34,buff,1); cmd=toupper(buff[0]);
2330: } while (isspace(cmd));
2331: move(14,35); clrtoeol();
2332: /* PROCESS USER COMMAND */
2333: switch(cmd) {
2334:
2335: case 'H': /* DISPLAY HELP */
2336: display_help();
2337: display_menu(&a_student,had_exam, had_quiz);
2338: break;
2339:
2340: case 'T': /* TRY CURRENT SET */
2341: try_set(student_number,set,§ion);
2342: display_menu(&a_student,had_exam, had_quiz);
2343: break;
2344:
2345: case 'V': /* VIEW PREVIOUS SET */
2346: view_previous(student_number,set,§ion);
2347: display_menu(&a_student,had_exam, had_quiz);
2348: break;
2349:
2350: case 'S': /* DISPLAY TERM SUMMARY */
2351: configResult=read_capa_config("term_summary_button",buff);
2352: if (configResult != 0 && configResult != -1 ) {
2353: if ((strcasecmp(buff,"no")==0)) {
2354: break;
2355: }
2356: }
2357: term_summary(student_number,set,§ion,TERM_SUMMARY);
2358: display_menu(&a_student,had_exam, had_quiz);
2359: break;
2360: case 'E': /* VIEW EXAM SUMMARY */
2361: if( had_exam ) {
2362: chdir(Exam_path);
2363: term_summary(student_number,Exam_set,§ion,EXAM_SUMMARY);
2364: display_menu(&a_student,had_exam, had_quiz);
2365: chdir(Orig_path);
2366: }
2367: break;
2368: case 'Q': /* VIEW QUIZ SUMMARY */
2369: if( had_quiz ) {
2370: chdir(Quiz_path);
2371: term_summary(student_number,Quiz_set,§ion,QUIZ_SUMMARY);
2372: display_menu(&a_student,had_exam, had_quiz);
2373: chdir(Orig_path);
2374: }
2375: break;
2376: case EOF: /* EXIT SYSTEM */
2377: case 'X': ex=1; break;
2378:
2379: default: /* INVALID COMMAND */
2380: /* printf("Invalid choice\n"); */
2381: break;
2382: }
2383: }
2384: }
2385:
2386: /* -------------------------------------------------------------------------- */
2387: /* DISPLAY WELCOME MESSAGE WHEN USER LOGS IN */
2388: /* -------------------------------------------------------------------------- */
2389: void /* RETURNS: (nothing) */
2390: welcome() /* ARGUMENTS: */
2391: { /* LOCAL VARIABLES: */
2392: FILE *fp; /* Welcome file pointer */
2393: char buf[TMP_LINE_LENGTH]; /* Input buffer */
2394:
2395: CLEAR();
2396: /* sprintf(buf,"This is your %d-time login to this set, good luck!",tries);
2397: addstr(buf);
2398: */
2399: if ((fp=fopen("welcome.msg","r"))!=NULL) {
2400: while (fgets(buf,TMP_LINE_LENGTH-1,fp)) addstr(buf);
2401: fclose(fp);
2402: }
2403: }
2404:
2405: void print_version()
2406: {
2407: printf("capalogin\n");
2408: printf(" CAPA version %s, %s\n",CAPA_VER,COMPILE_DATE);
2409: }
2410:
2411: /* ------------------------------------------------------------------------- */
2412: /* DRIVER: INITIALIZE AND GO TO LOGIN */
2413: /* ------------------------------------------------------------------------- */
2414: int
2415: main(int argc, char **argv)
2416: { /* LOCAL VARIABLES: */
2417: char student_number[MAX_STUDENT_NUMBER+1]; /* Student number */
2418: int set, /* Set number */
2419: section=0, /* Section number */
2420: result; /* stores result from read_capa_config */
2421: char filename[FILE_NAME_LENGTH]; /* Question filename buffer */
2422: #if defined(NeXT)
2423: char cwd[FILE_NAME_LENGTH];
2424: #endif
2425: char *class_path, buf[MAX_BUFFER_SIZE],*tty;
2426:
2427:
2428: if (argc > 1) { if (strcmp(argv[1],"-v") == 0) {print_version(); exit(0); } }
2429: #ifdef LOGIN_DBUG
2430: printf("Create login.DBUG file:: argc = %d\n",argc);
2431: sprintf(filename,"login.DBUG");
2432: if ((dfp=fopen(filename,"a"))==NULL) { printf("Error: can't open login debug\n"); return; }
2433: #endif /* LOGIN_DBUG */
2434: /* GET CURRENT SET NUMBER */
2435: for(set = 1; ; set++ ) {
2436: sprintf(filename,"set%d.qz",set);
2437: if(capa_access(filename, F_OK) == -1 ) break;
2438: }
2439: set--;
2440: #if defined(NeXT)
2441: class_path = getwd(cwd);
2442: if( class_path == NULL ) class_path = cwd;
2443: #else
2444: class_path = getcwd(NULL,512);
2445:
2446: #endif
2447: sprintf(Orig_path,"%s",class_path);
2448: free(class_path);
2449: /* ---------------------------------------------- CURSES INITIALIZATION */
2450: signal(SIGINT , kick_out);
2451: signal(SIGALRM, kick_out);
2452: signal(SIGFPE, SIG_IGN);
2453: initscr(); savetty(); cbreak(); noecho();
2454: time(&log_in_time);
2455: strncpy(in_t,ctime(&log_in_time),31);
2456: in_t[ strlen(in_t)-1 ]=0; /* Trash newline */
2457: tty=ttyname(0);
2458: if ( tty == NULL ) {
2459: strcpy(in_tty,"UNKNOWN");
2460: } else {
2461: strcpy(in_tty,tty);
2462: }
2463: result=read_capa_config("capalogin_goodbye_delay",buf);
2464: if (result != 0 && result != -1) {
2465: g_delay=atoi(buf);
2466: } else {
2467: g_delay=5;
2468: }
2469: result=read_capa_config("capalogin_inactivity_delay",buf);
2470: if (result != 0 && result != -1) {
2471: g_max_delay=atoi(buf);
2472: } else {
2473: g_max_delay=60;
2474: }
2475: welcome();
2476: strcpy(student_number, login(&set,§ion)); student_number[MAX_STUDENT_NUMBER] = 0;
2477: #ifdef LOGIN_DBUG
2478: fprintf(dfp,"login return:SNum=%s, set=%d, sec=%d\n", student_number,set, section); fflush(dfp);
2479: #endif
2480: menu_main(student_number,set,section);
2481: #ifdef LOGIN_DBUG
2482: fclose(dfp);
2483: #endif
2484: properly_logout(student_number);
2485: return 0;
2486: }
2487:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>