File:
[LON-CAPA] /
capa /
capa51 /
pProj /
capalogin.c
Revision
1.3:
download - view:
text,
annotated -
select for diffs
Mon Nov 8 22:30:02 1999 UTC (24 years, 9 months ago) by
albertel
Branches:
MAIN
CVS tags:
HEAD
- changed default to not allow viewing between answd and due
- added debug to scorer for when it won't quit
- fixed problems with blank question bodies in capasbin
- fixed displaying of answer boxes to work with mixed /AND questions
- fixed summary screens in both capalogin and capaweb to work, so that
non opened sets are not summaried
- fixed equation answers, so they can take array arguments for the
point specifications
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:
1146:
1147: switch( capa_check_answers(p,a,cnt) ) {
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 SIG_FAIL: move(S_ROW,S_COL); clrtoeol();
1176: mvaddstr(S_ROW,S_COL,"*Adjust Sig. Figs. ");
1177: *log_char='S'; can_answer=YAK;
1178: break;
1179: case UNIT_FAIL: move(S_ROW,S_COL); clrtoeol();
1180: mvaddstr(S_ROW,S_COL,"*Units incorrect ");
1181: *log_char='U'; can_answer=YAK;
1182: break;
1183: case UNIT_NOTNEEDED: move(S_ROW,S_COL); clrtoeol();
1184: mvaddstr(S_ROW,S_COL,"*Only a number required");
1185: *log_char='U'; can_answer=YAK;
1186: break;
1187: case NO_UNIT: move(S_ROW,S_COL); clrtoeol();
1188: mvaddstr(S_ROW,S_COL,"*Units required ");
1189: *log_char='u'; can_answer=YAK;
1190: break;
1191: case BAD_FORMULA:move(S_ROW,S_COL); clrtoeol();
1192: mvaddstr(S_ROW,S_COL,"*Unable to interpret formula");
1193: *log_char='F'; can_answer=YAK;
1194: break;
1195: case ANS_CNT_NOT_MATCH:
1196: move(S_ROW,S_COL); clrtoeol();
1197: mvaddstr(S_ROW,S_COL,"*Invalid number of answers");
1198: *log_char='C'; can_answer=YAK;
1199: break;
1200: case INCORRECT:
1201: if(*tried < TRY_BOUND) (*tried)++;
1202: if ( *tried < p->tries ) {
1203: can_answer=YAK;
1204: if( (p->tries - *tried) == 1 ) {
1205: sprintf(tmp_str,"*Incorrect, ONE try left!!");
1206: } else {
1207: sprintf(tmp_str,"*Incorrect, tries %2d/%2d ",*tried,p->tries);
1208: }
1209: } else {
1210: can_answer=NAY;
1211: sprintf(tmp_str, "*Incorrect, no more tries");
1212: }
1213: move(S_ROW,S_COL); clrtoeol();
1214: mvaddstr(S_ROW,S_COL, tmp_str);
1215: if( (can_answer == YAK) && (p->ans_op == ANS_AND) && (p->ans_cnt > 1) ) {
1216: sprintf(tmp_str, " Entering answer 1 of %3d ",p->ans_cnt);
1217: mvaddstr(A_ROW,S_COL,tmp_str);
1218: }
1219: *log_char='N';
1220: break;
1221: }
1222:
1223: return (can_answer);
1224: }
1225:
1226: int give_inhibited_response(Problem_t *p,char **a,int cnt,int *tried,int *log_char)
1227: {
1228: int can_answer;
1229: char tmp_str[MAX_BUFFER_SIZE];
1230:
1231:
1232: switch( capa_check_answers(p,a,cnt) ) {
1233:
1234:
1235: case EXACT_ANS: *log_char='Y'; break;
1236: case APPROX_ANS: *log_char='Y'; break;
1237: case SIG_FAIL: *log_char='S'; break;
1238: case UNIT_FAIL: *log_char='U'; break;
1239: case UNIT_NOTNEEDED: *log_char='U'; break;
1240: case NO_UNIT: *log_char='u'; break;
1241: case BAD_FORMULA:*log_char='F'; break;
1242: case INCORRECT: *log_char='N'; break;
1243: case ANS_CNT_NOT_MATCH: *log_char='C'; break;
1244: }
1245:
1246: if(*tried < TRY_BOUND) (*tried)++;
1247: if ( *tried < p->tries ) {
1248: can_answer=YAK;
1249: if( (p->tries - *tried) == 1 ) {
1250: sprintf(tmp_str,"*Answered, ONE try left!! ");
1251: } else {
1252: sprintf(tmp_str,"*Answered, tries %2d/%2d ",*tried,p->tries);
1253: }
1254: } else {
1255: can_answer=NAY;
1256: sprintf(tmp_str, "*Answered, no more tries ");
1257: }
1258: move(S_ROW,S_COL); clrtoeol();
1259: mvaddstr(S_ROW,S_COL, tmp_str);
1260: return (can_answer);
1261: }
1262:
1263: int ask_what_prob(int q_cnt, char *ans)
1264: {
1265: int not_ok=1,num,anslength,i,j;
1266: char buf[5],buf2[MAX_BUFFER_SIZE];
1267:
1268: move(14,35); clrtoeol();
1269: move(17,5); clrtoeol();
1270: do {
1271: move(14,35); clrtoeol();
1272: move(15,0); clrtoeol();
1273: mvaddstr(15,13,"What problem number:");
1274: move(17,0); clrtoeol();
1275: mvaddstr(17,16," 1 2 3 4 5");
1276: mvaddstr(18,16,"12345678901234567890123456789012345678901234567890");
1277: anslength=strlen(ans);
1278: for(i=0;i<=(anslength/50);i++) {
1279: if ( g_inhibit_response ) {
1280: for(j=50*i;(j<((i+1)*50))&&(j<anslength);j++) {
1281: if (ans[j]=='-')
1282: buf2[j-(50*i)]='-';
1283: else
1284: buf2[j-(50*i)]='A';
1285: }
1286: buf2[j-(50*i)]='\0';
1287: } else {
1288: strncpy(buf2,&(ans[50*i]),50);
1289: }
1290: buf2[50]='\0';
1291: mvaddstr(19+i,16,buf2);
1292: if (anslength > 50 ) {
1293: sprintf(buf2,"%3d-%3d",i*50+1,(i+1)*50);
1294: mvaddstr(19+i,5,buf2);
1295: }
1296: }
1297: do { get_input(15,34,buf,4); } while(!strlen(buf));
1298: sscanf(buf,"%d",&num);
1299: if (num<1 || num>q_cnt) {
1300: move(21,5); clrtoeol();
1301: mvaddstr(21,15," Error: Invalid problem number\n");
1302: } else {
1303: not_ok = 0;
1304: }
1305: } while (not_ok);
1306:
1307: return (num);
1308: }
1309:
1310: /* gather subjective answers from student */
1311:
1312: #define BS 8
1313: #define DEL 127
1314: #define ESC 27
1315:
1316: #define COLON 58
1317:
1318: #define EDIT_HEIGHT 21
1319: #define EDIT_WIDTH 80
1320: #define MENULINE EDIT_HEIGHT
1321:
1322: void refresh_editor (char **sbuf_pp,int cx,int cy) {
1323: int i;
1324: CLEAR();
1325: echo();
1326: mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move curser");
1327: mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
1328: mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
1329: for(i=0;i<EDIT_HEIGHT;i++) { mvaddstr(i,0,sbuf_pp[i]); }
1330: move(cy,cx); refresh(); noecho();
1331: }
1332:
1333: void init_editor(char*** sbuf_pp)
1334: {
1335: int ww=EDIT_WIDTH, hh=EDIT_HEIGHT,i;
1336: *sbuf_pp = (char **)capa_malloc(sizeof(char *),hh);
1337: for(i=0;i<hh;i++) {
1338: (*sbuf_pp)[i] = (char *)capa_malloc(sizeof(char)*ww+1,1);
1339: }
1340: CLEAR();echo();
1341: mvaddstr(MENULINE,0,"Type in the answer, use up, down, left, right keys to move cursor");
1342: mvaddstr(MENULINE+1,0,"Enter ctrl-e to exit and submit answer");
1343: mvaddstr(MENULINE+2,0,"Enter ctrl-f to forget answer");
1344: move(0,0); refresh(); noecho();
1345: }
1346:
1347: void remove_character(char** sbuf_pp,int *cx,int *cy)
1348: {
1349: int sx=(*cx)-1,sy=*cy;
1350: char temp,*temp_p;
1351: if (*cx==0) {
1352: int abovelen,curlen,diff,i,j;
1353: if (*cy==0) { beep();return;}
1354: abovelen=strlen(sbuf_pp[(*cy-1)]);
1355: curlen=strlen(sbuf_pp[*cy]);
1356: if (abovelen > 0) sbuf_pp[(*cy)-1][abovelen-1]='\0';
1357: if ((abovelen+curlen) < EDIT_WIDTH) {
1358: strcat(sbuf_pp[(*cy)-1],sbuf_pp[*cy]);
1359: memset(sbuf_pp[(*cy)],'\0',EDIT_WIDTH+1);
1360: temp_p=sbuf_pp[*cy];
1361: i=*cy;
1362: while(i<EDIT_HEIGHT-1) {
1363: sbuf_pp[i]=sbuf_pp[i+1];
1364: echo();move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);noecho();
1365: i++;
1366: }
1367: sbuf_pp[EDIT_HEIGHT-1]=temp_p;
1368: echo();move(EDIT_HEIGHT-1,0);CLRTOEOL();noecho();
1369: } else {
1370: diff=EDIT_WIDTH-abovelen;
1371: strncat(sbuf_pp[(*cy)-1],sbuf_pp[*cy],diff);
1372: i=diff;j=0;
1373: while(sbuf_pp[*cy][i]!='\0') {
1374: sbuf_pp[*cy][j]=sbuf_pp[*cy][i];
1375: i++;j++;
1376: }
1377: memset(&(sbuf_pp[(*cy)][j]),'\0',EDIT_WIDTH+1-j);
1378: }
1379: echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
1380: (*cy)--;
1381: echo();move(*cy,0); CLRTOEOL(); mvaddstr(*cy,0,sbuf_pp[*cy]);noecho();
1382: if ( EDIT_WIDTH == ((*cx)=(abovelen-1))) (*cx)--;
1383: if (abovelen==0) *cx=0;
1384: echo();move(*cy,*cx);noecho();
1385: } else {
1386: echo();move(sy,sx);noecho();
1387: temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
1388: sx++;
1389: while(temp!='\0') {
1390: echo(); ADDCH(temp); noecho();
1391: temp=sbuf_pp[sy][sx]=sbuf_pp[sy][sx+1];
1392: sx++;
1393: }
1394: echo(); ADDCH(' '); noecho();
1395: (*cx)--;
1396: }
1397: echo();move(*cy,*cx);noecho();
1398: }
1399:
1400: void break_line (char** sbuf_pp,int *cx,int *cy)
1401: {
1402: int sx=*cx,sy=*cy,i;
1403: if (sy < EDIT_HEIGHT-1) {
1404: capa_mfree(sbuf_pp[EDIT_HEIGHT-1]);
1405: i=EDIT_HEIGHT-1;
1406: while (i-1 > sy) {
1407: sbuf_pp[i]=sbuf_pp[i-1];
1408: move(i,0);CLRTOEOL();mvaddstr(i,0,sbuf_pp[i]);
1409: i--;
1410: }
1411: sbuf_pp[sy+1]=capa_malloc(sizeof(char)*EDIT_WIDTH+1,1);
1412: }
1413: strcat(sbuf_pp[sy+1],&(sbuf_pp[sy][sx]));
1414: memset(&(sbuf_pp[sy][sx]),'\0',EDIT_WIDTH+1-sx);
1415: *cx=0;
1416: (*cy)++;
1417: move(sy,0);CLRTOEOL();mvaddstr(sy,0,sbuf_pp[sy]);
1418: move(sy+1,0);CLRTOEOL();mvaddstr(sy+1,0,sbuf_pp[sy+1]);
1419: }
1420:
1421: /* FIXME catch funtion keys and others? */
1422: void handle_esc (unsigned char ca,unsigned char cb,char** sbuf_pp,int *cx,int *cy)
1423: {
1424: if( ca!='[') return;
1425: switch (cb) {
1426: case 'A':/* KEY_UP */
1427: if(*cy>0){
1428: (*cy)--;
1429: while(*cx>0 && sbuf_pp[*cy][(*cx)-1]=='\0') (*cx)--; /* goto end of line */
1430: } else {
1431: beep();
1432: }
1433: break;
1434: case 'B': /* KEY_DOWN */
1435: if (*cy<(EDIT_HEIGHT-1)) {
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 'C': /* KEY_RIGHT */
1443: if ( *cx<(EDIT_WIDTH-1) && sbuf_pp[*cy][(*cx)]!='\0' ) {
1444: (*cx)++;
1445: } else {
1446: if (*cy<(EDIT_HEIGHT-1)) {
1447: (*cy)++; *cx=0;
1448: } else {
1449: beep();
1450: }
1451: }
1452: break;
1453: case 'D': /* KEY_LEFT */
1454: if(*cx>0) {
1455: (*cx)--;
1456: } else {
1457: if(*cy>0) {
1458: (*cy)--;
1459: *cx=strlen(sbuf_pp[*cy]);
1460: if (*cx==EDIT_WIDTH) (*cx)--;
1461: } else {
1462: beep();
1463: }
1464: }
1465: break;
1466: default: beep(); return; break;
1467: }
1468: echo(); move(*cy,*cx); refresh(); noecho();
1469: }
1470:
1471: void handle_error (unsigned char c,char** sbuf_pp,int cx,int cy)
1472: {
1473: beep();
1474: }
1475:
1476: /*FIXME Slower than whale shit*/
1477: void insert_character(unsigned char c,char** sbuf_pp,int *cx,int *cy)
1478: {
1479: int sx=*cx,sy=*cy;
1480: unsigned char temp;
1481: while(c!='\0') {
1482: if (sx == EDIT_WIDTH) {
1483: sx=0;sy++;
1484: if (sy == EDIT_HEIGHT) {
1485: sy--;sx=EDIT_WIDTH;c='\0';break;
1486: }
1487: }
1488: echo(); ADDCH(c); noecho();
1489: temp=sbuf_pp[sy][sx];
1490: sbuf_pp[sy][sx]=c;
1491: c=temp;
1492: sx++;
1493: }
1494: sbuf_pp[sy][sx]=c;
1495: (*cx)++;
1496: if (*cx == EDIT_WIDTH) {
1497: *cx=0;(*cy)++;
1498: if (*cy == EDIT_HEIGHT) {
1499: (*cy)--;*cx=EDIT_WIDTH-1;
1500: }
1501: }
1502: move(*cy,*cx);refresh();
1503: }
1504:
1505: int handle_keystrokes_editor(char** sbuf_pp)
1506: {
1507: int done = 0, forget = 0, cx=0,cy=0;
1508: unsigned char c,ca,cb;
1509:
1510: while (!done) {
1511: move(cy,cx);refresh();
1512: c=getch();
1513: switch(c) {
1514: case BS: case DEL:
1515: remove_character(sbuf_pp,&cx,&cy);
1516: break;
1517: case CR: case LF:
1518: break_line(sbuf_pp,&cx,&cy);
1519: break;
1520: case ESC:
1521: ca=getch();cb=getch();
1522: handle_esc(ca,cb,sbuf_pp,&cx,&cy);
1523: break;
1524: case 5: /*ctrl-e*/
1525: done=1;
1526: break;
1527: case 6: /*ctrl-f*/
1528: done=1;
1529: forget=1;
1530: break;
1531: case 12:
1532: refresh_editor(sbuf_pp,cx,cy);
1533: break;
1534: default:
1535: if (c < 32 || c>126) {
1536: handle_error(c,sbuf_pp,cx,cy);
1537: } else {
1538: insert_character(c,sbuf_pp,&cx,&cy);
1539: }
1540: break;
1541: }
1542: }
1543: return forget;
1544: }
1545:
1546: int editor(char*** sbuf_pp)
1547: {
1548: init_editor(sbuf_pp);
1549: return handle_keystrokes_editor(*sbuf_pp);
1550: }
1551:
1552:
1553: int
1554: answer_subjective(student_number,set,section,prob)
1555: char *student_number;
1556: int set;
1557: int *section;
1558: int prob;
1559: {
1560: int i,length;
1561: char date_str[DATE_LENGTH];
1562: char **sbuf_pp,answer[(EDIT_HEIGHT*(EDIT_WIDTH+1))+1];
1563: char submissions_str[(EDIT_HEIGHT*(EDIT_WIDTH+1))+MAX_BUFFER_SIZE];
1564: time_t curtime;
1565:
1566: time(&curtime);
1567: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1568: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1569: sprintf(answer,"Sorry, the due date was: %s",date_str);
1570: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1571: return 0;
1572: }
1573:
1574: if (editor(&sbuf_pp)) { return 0; }
1575:
1576: answer[0]='\0';
1577: for(i=0;i<EDIT_HEIGHT;i++) {
1578: if (strlen(sbuf_pp[i]) > 0) {
1579: strcat(answer,sbuf_pp[i]);
1580: length=strlen(answer);
1581: answer[length]='\n';
1582: answer[length+1]='\0';
1583: }
1584: capa_mfree((char *)sbuf_pp[i]);
1585: }
1586: capa_set_subjective(set,prob,student_number,answer);
1587: sprintf(submissions_str,"%d\t%s\t",prob,answer);
1588: log_submissions(student_number,set,submissions_str);
1589: capa_mfree((char *)sbuf_pp);
1590: return 1;
1591: }
1592:
1593: void set_entry_tries(int *tried, char *tries, int num, int num_questions) {
1594: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1595: if(tried[num] < 10 ) {
1596: tries[3*num] = ' ';
1597: tries[3*num+1] = tried[num] + '0';
1598: if(num < num_questions-1) tries[3*num+2] = ',';
1599: } else {
1600: tries[3*num] = (int)(tried[num]/10) + '0';
1601: tries[3*num+1] = (tried[num] % 10) + '0';
1602: if(num < num_questions-1) tries[3*num+2] = ',';
1603: }
1604: } else {
1605: tries[3*num] = ' ';
1606: tries[3*num+1] = 1 + '0';
1607: if(num < num_questions-1) tries[3*num+2] = ',';
1608: }
1609: }
1610:
1611: /* -------------------------------------------------------------------------- */
1612: /* LET THE USER ANSWER THE CURRENT PROBLEM SET QUESTIONS */
1613: /* -------------------------------------------------------------------------- */
1614: void
1615: try_set(student_number,set,section)
1616: char *student_number;
1617: int set;
1618: int *section;
1619: {
1620: char a_student_number[MAX_STUDENT_NUMBER+1];
1621: time_t curtime;
1622: T_header header;
1623: Problem_t *first_problem, *p;
1624: T_entry entry;
1625: char answer[256], *a_str, **ans_strs;
1626: int num, offset, num_questions, start_from, leng;
1627: char *log_string,submissions_str[MAX_BUFFER_SIZE];
1628: int *tried,answered;
1629: int scr_idx=1, display=1, second_scr, canAnswer;
1630: int usr_command, whereto, allow_hint=0, ex=0;
1631: char u_input[64], date_str[DATE_LENGTH], one_line[81];
1632: int log_char, i, j, allow_n, allow_p, allow_subj;
1633:
1634: strncpy(a_student_number,student_number,MAX_STUDENT_NUMBER+1);
1635: time(&curtime); /* Is due date past? */
1636: /* ---------------------------------------- check due date */
1637: #ifndef NO_DATE_CHECK
1638: /* ===> if ( compare_datetime(curtime,header.due_date) > 0) { */
1639: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1640: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1641: sprintf(answer," Sorry, the due date was: %s",date_str);
1642: move(17,1); clrtoeol(); mvaddstr(17,15,answer); mypause(19,17);
1643: return;
1644: }
1645: #ifdef LOGIN_DBUG
1646: fprintf(dfp,"Tryset():(sec=%d,set=%d)[%s]\n",*section,set,date_str); fflush(dfp);
1647: #endif /* LOGIN_DBUG */
1648: #endif /* NO_DATE_CHECK */
1649:
1650: offset=capa_get_entry(&entry,student_number,set);
1651: capa_get_header(&header,set);
1652: if (offset<0) offset = -offset; /* newly created entry */
1653:
1654: #ifdef LOGIN_DBUG
1655: fprintf(dfp,"P set=%d,SN=%s,ANS=%s,TRY=%s\n",set,a_student_number,entry.answers,entry.tries); fflush(dfp);
1656: #endif
1657: num = capa_parse(set,&first_problem,a_student_number,&num_questions,NULL);
1658:
1659: #ifdef LOGIN_DBUG
1660: fprintf(dfp,"ParseSource:=%d\n",num); fflush(dfp);
1661: #endif /* LOGIN_DBUG */
1662:
1663: /* DEBUGGING: make sure num_questions is plausible */
1664: if (num_questions>1000 || num_questions<=0) properly_logout(student_number);
1665:
1666: start_from=ask_what_prob(num_questions,entry.answers);
1667:
1668: /* initialize log string to all '-' */
1669: tried = (int *)capa_malloc(num_questions+1,sizeof(int));
1670: log_string = (char *)capa_malloc(num_questions+1,sizeof(char));
1671: for (num=0; num<num_questions; num++) {
1672: log_string[num]='-';
1673: sscanf(entry.tries + 3*num,"%d,",&(tried[num]) );
1674: }
1675: log_string[num_questions]=0;
1676: capa_set_login_time(student_number,set);
1677: for (num=0,p=first_problem; p; ){
1678: if( start_from > 1 ) {
1679: num=start_from-1;
1680: for (p=first_problem; start_from > 1 && p->next; start_from--)
1681: p=p->next;
1682: start_from = 0;
1683: }
1684: if (display) {
1685: /* DISPLAY QUESTION */
1686: CLEAR();
1687: second_scr = display_prob_scr(p->question,scr_idx);
1688: allow_subj = 0;
1689: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
1690: allow_subj = 1;
1691: move(A_ROW,A_COL); clrtoeol();
1692: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1693: }
1694: mvaddstr(S_ROW,0,"OPTION/ANSWER");
1695: mvaddstr(O_ROW,0,"Options :M = Main Menu :7 = go to # 7");
1696: allow_n = allow_p = 0;
1697: if( second_scr && (scr_idx == 1) ) {
1698: mvaddstr(O_ROW,E_COL,":N = Next screen");
1699: allow_n=1;
1700: }
1701: if( second_scr && (scr_idx == 2) ) {
1702: mvaddstr(O_ROW,E_COL,":P = Prev screen");
1703: allow_p=1;
1704: }
1705:
1706: mvaddstr(O_ROW,R_COL,"RETURN = Enter/Execute");
1707:
1708: if (g_inhibit_response ) {
1709: canAnswer = show_prior_inhibited_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1710: } else {
1711: canAnswer = show_prior_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1712: }
1713:
1714: }
1715: mvaddstr(X_ROW,X_COL,":X = eXit");
1716:
1717: /* <= */
1718:
1719:
1720:
1721: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1722: display=0; usr_command=C_DONTCARE;
1723: /* DEFAULT ACTIONS on empty input */
1724: if(!strlen(u_input)) { usr_command = (p->next? C_FORWARD : C_MENU); } else {
1725: if( u_input[0] == ':' ) {
1726: switch(toupper( u_input[1] )) {
1727: case 'H': if( allow_hint ) { usr_command=C_HINT; } break;
1728: case 'M': usr_command=C_MENU; break;
1729: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
1730: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
1731: case 'X': usr_command=C_EXIT; break;
1732: case 'A': if( allow_subj ) { usr_command=C_SUBJANS; } break;
1733: default : sscanf(u_input,":%d",&whereto);
1734: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
1735: break;
1736: }
1737: } else { /* user entered some answer */
1738: if( p->ans_op == ANS_AND ) {
1739: if(canAnswer) { usr_command=C_ANSWER;
1740: ans_strs = (char **)capa_malloc(sizeof(char *), p->ans_cnt);
1741: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1742: strcpy(ans_strs[0],u_input);
1743: for(i=1;i<p->ans_cnt;i++) {
1744: mvaddstr(A_ROW,A_COL," ");
1745: mvaddstr(A_ROW,A_COL,ans_strs[i-1]);
1746: sprintf(one_line, " Entering answer %3d of %3d ", i+1,p->ans_cnt);
1747: mvaddstr(A_ROW,S_COL,one_line);
1748: mvaddstr(S_ROW,A_COL," ");
1749: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1750: ans_strs[i] = (char *)capa_malloc(strlen(u_input)+1,1);
1751: strcpy(ans_strs[i],u_input);
1752:
1753: }
1754:
1755: /* now in ans_strs[][] are user inputs */
1756:
1757: }
1758: } else { /* one answer or ANS_OR */
1759: ans_strs = (char **)capa_malloc(sizeof(char *), 1);
1760: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1761: strcpy(ans_strs[0], u_input);
1762: if(canAnswer) { usr_command=C_ANSWER;
1763: mvaddstr(S_ROW,A_COL," ");
1764: mvaddstr(A_ROW,A_COL," ");
1765: mvaddstr(A_ROW,A_COL,ans_strs[0]); }
1766: }
1767: } /* end if u_input[0] == ':' */
1768: } /* end if !strlen(u_input) */
1769:
1770:
1771:
1772:
1773:
1774: /* PROCESS USER COMMAND */
1775: switch(usr_command) {
1776: case C_FORWARD: /* Forwards */
1777: if (p->next) {
1778: p=p->next; num++;
1779: display=1; allow_hint=0; scr_idx=1;
1780: } else
1781: mvaddstr(X_ROW,R_COL,"RETURN = Main Menu ");
1782: break;
1783: case C_NEXTSCR: scr_idx = 2; display=1;
1784: break;
1785: case C_PREVSCR: scr_idx = 1; display=1;
1786: break;
1787: case C_EXIT: /* Exit */
1788: ex=1; p=0; break;
1789: case C_MENU: /* Return to main menu */
1790: p=0; break;
1791: case C_HINT: /* Hint */
1792: if (! p->hint) break;
1793: display_hint(p->hint);
1794: display=1;
1795: break;
1796: case C_ANSWER: /* Answer question */
1797: {
1798: if(p->ans_type== ANSWER_IS_SUBJECTIVE) {
1799: move(A_ROW,A_COL); clrtoeol();
1800: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1801: capa_mfree(ans_strs[0]);
1802: break;
1803: }
1804: if( p->ans_op == ANS_AND ) {
1805: leng = 0;
1806: for(i=0;i<p->ans_cnt;i++) {
1807: leng += (strlen((char *)ans_strs[i]) + 2);
1808: }
1809: a_str = (char *)capa_malloc(leng+1,1);
1810: a_str[0]=0;
1811: strcat(a_str,ans_strs[0]);
1812: if ( is_all_ws(ans_strs[0]) ) break;
1813: trim_response_ws(ans_strs[0]);
1814: for(i=1;i<p->ans_cnt;i++) {
1815: strcat(a_str,"\t");
1816: strcat(a_str,ans_strs[i]);
1817: if ( is_all_ws(ans_strs[i]) ) break;
1818: trim_response_ws(ans_strs[i]);
1819: }
1820: if (i < p->ans_cnt) {
1821: display=1; /*handle early breaks out of the*/
1822: break; /*loop which mean typed only ws */
1823: }
1824: } else { /* only one answer */
1825: leng = (strlen((char *)ans_strs[0]) + 2);
1826: a_str = (char *)capa_malloc(leng+1,1);
1827: a_str[0]=0;
1828: strcat(a_str,ans_strs[0]);
1829: if ( is_all_ws(ans_strs[0]) ) break;
1830: trim_response_ws(ans_strs[0]);
1831: }
1832:
1833: sprintf(submissions_str,"%d\t%s\t",num+1,a_str);
1834: log_submissions(student_number,set,submissions_str);
1835:
1836: {
1837: int cnt=((p->ans_op==ANS_AND)?p->ans_cnt:1);
1838: if (g_inhibit_response) {
1839: canAnswer = give_inhibited_response(p, ans_strs,cnt,
1840: &(tried[num]),&log_char);
1841: } else {
1842: canAnswer = give_response(p, ans_strs,cnt, &(tried[num]),&log_char);
1843: }
1844: }
1845: if( p->ans_op == ANS_AND ) {
1846: for(i=0;i<p->ans_cnt;i++) {
1847: capa_mfree( (char *)ans_strs[i] );
1848: }
1849:
1850: } else { /* there is only one user answer */
1851: capa_mfree( (char *)ans_strs[0] );
1852:
1853: }
1854: capa_mfree((char *)ans_strs);
1855: capa_mfree( (char *)a_str );
1856:
1857: if (p->hint &&
1858: (
1859: (p->show_hint<=tried[num])||
1860: (log_char == 'y') ||
1861: (log_char == 'Y')
1862: )
1863: ){
1864: allow_hint=1;
1865: mvaddstr(X_ROW,H_COL,":H = Show Hint");
1866: }
1867: switch(log_char) {
1868: case 'U': case 'u': case 'S': case 'F':
1869: entry.answers[num]='N'; break;
1870: case 'Y': allow_hint=1; mvaddstr(X_ROW,H_COL,":H = Show Hint"); /* fall through here */
1871: default: entry.answers[num]=log_char; break;
1872: }
1873: log_string[num]=log_char;
1874:
1875: log_attempt(student_number,set,*section,log_string);
1876: /* for (i=0; i<num_questions; i++) { log_string[i] = '-' ; } */
1877: set_entry_tries(tried,entry.tries,num,num_questions);
1878: log_string[num]='-';
1879: /* ------------------------------ check due date */
1880: time(&curtime);
1881: /* ===> if (compare_datetime(curtime,header.due_date) > 0) { */
1882: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1883: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1884: sprintf(answer,"Sorry, the due date was: %s",date_str);
1885: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1886: } else {
1887: capa_set_entry(&entry,student_number,set,offset);
1888: }
1889: } break;
1890: case C_JUMP: /* Jump to specific question number */
1891: num=whereto-1;
1892: for (p=first_problem; whereto > 1 && p->next; whereto--)
1893: p=p->next;
1894: display=1; allow_hint=0; scr_idx=1;
1895: break;
1896: case C_SUBJANS:
1897: answered=answer_subjective(student_number,set,section,num+1);
1898: if (answered) {
1899: tried[num]++;
1900: if (p->hint && ((p->show_hint<=tried[num]))) { allow_hint=1; }
1901: entry.answers[num]='0';
1902: log_string[num]='A';
1903: log_attempt(student_number,set,*section,log_string);
1904: log_string[num]='-';
1905: set_entry_tries(tried,entry.tries,num,num_questions);
1906: capa_set_entry(&entry,student_number,set,offset);
1907: }
1908: display=1;
1909: break;
1910: case C_DONTCARE: break;
1911: }
1912: }
1913: for (i=0,j=0, num=0; num<num_questions; num++) {
1914: j = j + (header.weight[num] - '0');
1915: if((entry.answers[num]=='Y') || (entry.answers[num]=='y'))
1916: i = i + (header.weight[num] - '0');
1917: if( entry.answers[num] >= '0' && entry.answers[num] <= '9' ) {
1918: i = i + (entry.answers[num] - '0');
1919: }
1920: if((entry.answers[num]=='E') || (entry.answers[num]=='e'))
1921: j = j - (header.weight[num] - '0');
1922: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1923: if(tried[num] < 10 ) {
1924: entry.tries[3*num] = ' ';
1925: entry.tries[3*num+1] = tried[num] + '0';
1926: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1927: } else {
1928: entry.tries[3*num] = (int)(tried[num]/10) + '0';
1929: entry.tries[3*num+1] = (tried[num] % 10) + '0';
1930: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1931: }
1932: } else {
1933: entry.tries[3*num] = ' ';
1934: entry.tries[3*num+1] = 1 + '0';
1935: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1936: }
1937: }
1938: capa_mfree(header.weight);
1939: capa_mfree(header.partial_credit);
1940:
1941: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1942: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1943: /* ------- original code , should check due date before save it
1944:
1945: time(&curtime);
1946: if (compare_datetime(curtime,header.due_date) > 0) {
1947: if( capa_check_date(CHECK_DUE_DATE,*section,set) > 0 ) {
1948: need to deal with due_date
1949: sprintf(answer,"Sorry, the due date was: %s",header.due_date);
1950: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1951: } else {
1952: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1953: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1954:
1955: capa_set_entry(&entry,student_number,set,offset);
1956: }
1957: ------ */
1958: /* FREE UP MALLOC'ED SPACE (VERY IMPORTANT) */
1959: capa_mfree(entry.answers);
1960: capa_mfree(entry.tries);
1961: free_problems(first_problem);
1962: /* log_attempt(student_number,set,*section,log_string); */
1963: capa_mfree(log_string);
1964: capa_mfree((char*)tried);
1965: if (ex) properly_logout(student_number);
1966:
1967: }
1968:
1969: #define COL_ONE 1
1970: #define COL_TWO 17
1971: #define COL_THREE 34
1972: #define COL_FOUR 43
1973: #define COL_FIVE 69
1974:
1975: /* ------------------------------------------------------------------------- */
1976: /* REVIEW PREVIOUS PROBLEM SETS */
1977: /* ------------------------------------------------------------------------- */
1978: void /* RETURNS: (nothing) */
1979: view_previous(student_number,set,section) /* ARGUMENTS: */
1980: char *student_number; /* Student number */
1981: int set; /* Set number */
1982: int *section; /* Section number */
1983: { /* LOCAL VARIABLES: */
1984: T_entry entry; /* Database entry */
1985: Problem_t *first_problem, /* Pointer to first problem */
1986: *problem; /* Previous problem */
1987: int num_questions, /* Total # of questions */
1988: ex=0, /* Exit system flag */
1989: display=1, /* Redraw flag */
1990: usr_command,
1991: whereto,
1992: allow_hint=0, allow_explain=0;
1993: int num; /* Temporary variable */
1994: char buf[4], /* Command input buffer */
1995: aLine[MAX_BUFFER_SIZE];
1996: T_header header; /* Set header */
1997: time_t curtime; /* Current time */
1998: double upper_ans;
1999: char fmt_ans[ANSWER_STRING_LENG], goto_str[ANSWER_STRING_LENG],
2000: tmp_str[ANSWER_STRING_LENG];
2001: int scr_idx=1, second_scr, allow_n, allow_p;
2002:
2003: /* QUERY USER FOR SET */
2004: move(15,5); /* deleteln(); */
2005: addstr(" Which set would you like to view?");
2006: mvaddstr(16,15, "Enter a set number and press ENTER/RETURN");
2007: move(17,1); clrtoeol(); /* erase Enter a command ... */
2008: do { get_input(15,51,buf,3); } while(!strlen(buf));
2009: sscanf(buf,"%d",&num);
2010: if (num<1 || num>set) {
2011: move(17,5); clrtoeol();
2012: mvaddstr(17,15," Error: Invalid previous set number\n");
2013: mypause(19,17); return;
2014: }
2015: /* ------------------------------------ answer date */
2016: time(&curtime);
2017: /* ===> if (compare_datetime(curtime,header.answer_date) < 0) { */
2018: if ( capa_check_date(CHECK_ANS_DATE,student_number,*section,num) < 0 ) {
2019: move(16,1); clrtoeol();
2020: move(17,5); clrtoeol();
2021: mvaddstr(17,15," Answers are not yet available\n"); mypause(19,17); return;
2022: }
2023:
2024: /* LOAD IN THE INFO NEEDED */
2025: capa_get_header(&header,num);
2026: capa_get_entry(&entry,student_number,num);
2027: capa_parse(num,&first_problem,student_number,&num_questions,NULL);
2028: sprintf(goto_str,"#=go to problem #, [%d problems]", num_questions);
2029: for (num=0,problem=first_problem; problem; ) {
2030: if (display) {
2031: allow_hint = allow_explain=0;
2032: allow_n = allow_p = 0;
2033: CLEAR();
2034: second_scr = display_prob_scr(problem->question,scr_idx);
2035: if( problem->ans_type == ANSWER_IS_FLOAT ) {
2036: upper_ans = (double)atof(problem->answer);
2037: sprintf(fmt_ans, problem->ans_fmt, upper_ans);
2038: } else {
2039: sprintf(fmt_ans, "%s", problem->answer);
2040: }
2041: if( problem->ans_unit ) {
2042: sprintf(tmp_str, "Answer: %s %s",fmt_ans,problem->unit_str);
2043: } else {
2044: sprintf(tmp_str, "Answer: %s",fmt_ans);
2045: }
2046: mvaddstr(S_ROW,COL_ONE,tmp_str);
2047:
2048: switch(entry.answers[num]) {
2049: case 'Y': mvaddstr(S_ROW,COL_FOUR,"CORRECT "); break;
2050: case 'y': mvaddstr(S_ROW,COL_FOUR,"HANDIN CORRECT "); break;
2051: case '-': mvaddstr(S_ROW,COL_FOUR,"UNANSWERED "); break;
2052: case 'e': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2053: case 'E': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2054: case 'n': mvaddstr(S_ROW,COL_FOUR,"HANDIN INCORRECT"); break;
2055: case 'N': mvaddstr(S_ROW,COL_FOUR,"INCORRECT "); break;
2056: default : if(entry.answers[num] >= '0' && entry.answers[num] <= '9') {
2057: sprintf(aLine,"HAND-GRADED %c/%c ",entry.answers[num],
2058: header.weight[num]);
2059: mvaddstr(S_ROW,COL_FOUR,aLine);
2060: }
2061: break;
2062: }
2063: mvaddstr(S_ROW,COL_FIVE,"OPTION:");
2064:
2065: mvaddstr(O_ROW,COL_ONE,"M=Main menu");
2066: if( second_scr && scr_idx == 1) {
2067: mvaddstr(O_ROW,COL_TWO,"N=Next screen");
2068: allow_n = 1;
2069: }
2070: if( second_scr && scr_idx == 2) {
2071: mvaddstr(O_ROW,COL_TWO,"P=Prev screen");
2072: allow_p = 1;
2073: }
2074: mvaddstr(O_ROW,COL_THREE,"X=eXit");
2075: mvaddstr(O_ROW,COL_FOUR, "RETURN=Enter/Execute");
2076: if ( problem->hint &&
2077: (
2078: (problem->show_hint <= problem->tries) ||
2079: (entry.answers[num] == 'Y') ||
2080: (entry.answers[num] == 'y')
2081: )
2082: ) {
2083: allow_hint=1; mvaddstr(O_ROW,COL_FIVE,"H=Hint");
2084: }
2085: mvaddstr(X_ROW,COL_ONE,goto_str);
2086: if (problem->next)
2087: mvaddstr(X_ROW,COL_FOUR,"RETURN=next problem");
2088: else
2089: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2090: if ( problem->explain ) { allow_explain=1; mvaddstr(X_ROW,COL_FIVE,"E=Explain"); }
2091:
2092: }
2093: get_input(S_ROW,COL_FIVE+7,buf,3);
2094: display=0; usr_command=C_DONTCARE;
2095: /* DEFAULT ACTIONS on empty input */
2096: if(!strlen(buf)) { usr_command = (problem->next? C_FORWARD : C_MENU); } else {
2097: switch(toupper(buf[0])) {
2098: case 'X': usr_command=C_EXIT; break;
2099: case 'M': usr_command=C_MENU; break;
2100: case 'H': usr_command=C_HINT; break;
2101: case 'E': usr_command=C_EXPLAIN; break;
2102: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
2103: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
2104: default : sscanf(buf,"%d",&whereto);
2105: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
2106: break;
2107: }
2108: }
2109:
2110:
2111: /* PROCESS USER COMMAND */
2112: switch(usr_command) {
2113: case C_FORWARD: /* FORWARDS ONE */
2114: if (problem->next) {
2115: problem=problem->next; display=1; scr_idx = 1; num++;
2116: } else
2117: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2118: break;
2119: case C_HINT: /* HINT */
2120: if(allow_hint) {
2121: display_hint(problem->hint);
2122: display=1;
2123: allow_hint = 0;
2124: }
2125: break;
2126: case C_EXPLAIN: /* Explain */
2127: if(allow_explain) {
2128: display_hint(problem->explain); display=1;
2129: allow_explain=0;
2130: }
2131: break;
2132: case C_NEXTSCR: scr_idx = 2; display=1;
2133: break;
2134: case C_PREVSCR: scr_idx = 1; display=1;
2135: break;
2136: case C_EXIT: /* EXIT SYSTEM */
2137: ex=1; problem=0; break;
2138:
2139: case C_MENU: /* RETURN TO MAIN MENU */
2140: problem=0; break;
2141:
2142: case C_JUMP: /* JUMP TO SPECIFIC PROBLEM # */
2143: num=whereto-1;
2144: for (problem=first_problem; whereto > 1 && problem->next; whereto--)
2145: problem=problem->next;
2146: display=1;
2147: scr_idx = 1;
2148: break;
2149: case C_TIME: break;
2150: case C_DONTCARE: break;
2151: }
2152: }
2153:
2154: /* FREE UP MALLOC'ED SPACE - VERY IMPORTANT */
2155: capa_mfree(header.weight);
2156: capa_mfree(header.partial_credit);
2157: capa_mfree(entry.answers);
2158: capa_mfree(entry.tries);
2159: free_problems(first_problem);
2160:
2161: if (ex) properly_logout(student_number);
2162: }
2163:
2164: /* -------------------------------------------------------------------------- */
2165: /* DISPLAY HELP SCREEN */
2166: /* -------------------------------------------------------------------------- */
2167: void /* RETURNS: (nothing) */
2168: display_help() /* ARGUMENTS: (none) */
2169: { /* LOCAL VARIABLES: */
2170: FILE *fp; /* Welcome file pointer */
2171: char buf[255]; /* Input buffer */
2172:
2173: CLEAR();
2174: if ((fp=fopen("help.msg","r"))!=NULL) {
2175: while (fgets(buf,255,fp)) addstr(buf);
2176: fclose(fp);
2177: }
2178: mypause(22,20);
2179: }
2180:
2181:
2182: /* A class directory must have */
2183: /* records/ */
2184: /* */
2185: /* returns: 0 structure is correct, but no set.db files */
2186: /* -1 structure is not correct */
2187: /* >=1 the last set.db */
2188:
2189: int
2190: check_class_get_set(dir_path) char *dir_path;
2191: {
2192: char f_name[1024];
2193: int set;
2194:
2195: if( capa_access(dir_path, F_OK) == 0 ) { /* class dir exists */
2196: sprintf(f_name,"%s/records",dir_path);
2197: if( capa_access(f_name, F_OK) == 0 ) { /* class/records dir exists */
2198: for(set = 1; ; set++ ) {
2199: sprintf(f_name,"%s/records/set%d.db",dir_path,set);
2200: if(capa_access(f_name, F_OK) == -1 ) break;
2201: }
2202: set--;
2203: } else {
2204: set = -1;
2205: }
2206: } else {
2207: set = -1;
2208: }
2209: return (set);
2210: }
2211: /* -------------------------------------------------------------------------- */
2212: /* Get Exam and Quiz Path */
2213: /* return 0, 1, 2, 3 */
2214: /* -------------------------------------------------------------------------- */
2215: int
2216: check_exam_quiz_f()
2217: {
2218: char buf[MAX_BUFFER_SIZE];
2219: int result = 0, configResult=0;
2220:
2221: #ifdef LOGIN_DBUG
2222: fprintf(dfp,"CHECK EXAM Access() success,and open(),%s\n",buf); fflush(dfp);
2223: #endif
2224: configResult=read_capa_config("exam_path",buf);
2225: if (configResult != 0 && configResult != -1) {
2226: Exam_set = check_class_get_set(buf);
2227: if(Exam_set > 0 ) {
2228: result = 1;
2229: sprintf(Exam_path,buf);
2230: }
2231: }
2232: #ifdef LOGIN_DBUG
2233: fprintf(dfp,"CHECK EXAM = %d,%s\n", result,Exam_path); fflush(dfp);
2234: #endif
2235: configResult=read_capa_config("quiz_path",buf);
2236: if (configResult != 0 && configResult != -1) {
2237: Quiz_set = check_class_get_set(buf);
2238: if(Quiz_set > 0 ) {
2239: result = (result | 2);
2240: sprintf(Quiz_path,buf);
2241: }
2242: }
2243:
2244: return (result);
2245: }
2246:
2247: /* -------------------------------------------------------------------------- */
2248: /* DISPLAY MAIN MENU */
2249: /* -------------------------------------------------------------------------- */
2250: void /* RETURNS: (nothing) */
2251: display_menu(student, exam_f, quiz_f)
2252: T_student *student;
2253: int exam_f, quiz_f;
2254: {
2255: char buff[MAX_BUFFER_SIZE];
2256: int c_y,configResult,term_summary_button=1;
2257:
2258: configResult=read_capa_config("term_summary_button",buff);
2259: if (configResult != 0 && configResult != -1 ) {
2260: if (strcasecmp(buff,"no")==0) {
2261: term_summary_button=0;
2262: }
2263: }
2264:
2265: CLEAR();
2266:
2267: mvaddstr(1,10,student->s_nm);
2268: sprintf(buff,"Section: %d",student->s_sec);
2269: mvaddstr(1,50,buff);
2270:
2271: mvaddstr( 4,25," MAIN MENU"); c_y = 6;
2272: mvaddstr( c_y,25,"H=Help"); c_y++;
2273: if (term_summary_button) { mvaddstr( c_y,25,"S=Summary"); c_y++; }
2274: mvaddstr( c_y,25,"T=Try set"); c_y++;
2275: mvaddstr( c_y,25,"V=View previous set"); c_y++;
2276: if(exam_f) { mvaddstr( c_y,25,"E=view Exam summary"); c_y++; }
2277: if(quiz_f) { mvaddstr( c_y,25,"Q=view Quiz summary"); c_y++; }
2278: mvaddstr( c_y,25,"X=eXit system");
2279:
2280: mvaddstr(14,25,"COMMAND:");
2281:
2282: mvaddstr(17, 5,"Enter a command from the list above and press ENTER/RETURN");
2283: }
2284:
2285: /* -------------------------------------------------------------------------- */
2286: /* CONTROL MAIN MENU SELECTIONS */
2287: /* -------------------------------------------------------------------------- */
2288: void /* RETURNS: (nothing) */
2289: menu_main(student_number,set,section) /* ARGUMENTS: */
2290: char *student_number; /* Student number */
2291: int set; /* Set number */
2292: int section; /* Section number */
2293: { /* LOCAL VARIABLES: */
2294: int ex=0, /* Exit system flag */
2295: cmd; /* User command */
2296: char buff[MAX_BUFFER_SIZE]; /* User command buffer */
2297: T_student a_student;
2298: int had_exam, had_quiz, outcome,configResult;
2299:
2300: #ifdef LOGIN_DBUG
2301: fprintf(dfp,"MENU in %s sec=%d\n", student_number,section); fflush(dfp);
2302: #endif
2303:
2304: outcome = check_exam_quiz_f();
2305: had_exam = outcome & 1;
2306: had_quiz = outcome & 2;
2307:
2308: #ifdef LOGIN_DBUG
2309: fprintf(dfp,"After check %d\n", outcome); fflush(dfp);
2310: #endif
2311:
2312: capa_get_student(student_number,&a_student);
2313:
2314: g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set,section);
2315: if (g_inhibit_response < 0 ) g_inhibit_response=0;
2316:
2317: display_menu(&a_student,had_exam, had_quiz);
2318: while (!ex) {
2319: do {
2320: buff[0] = ' '; buff[1] = 0;
2321: get_input(14,34,buff,1); cmd=toupper(buff[0]);
2322: } while (isspace(cmd));
2323: move(14,35); clrtoeol();
2324: /* PROCESS USER COMMAND */
2325: switch(cmd) {
2326:
2327: case 'H': /* DISPLAY HELP */
2328: display_help();
2329: display_menu(&a_student,had_exam, had_quiz);
2330: break;
2331:
2332: case 'T': /* TRY CURRENT SET */
2333: try_set(student_number,set,§ion);
2334: display_menu(&a_student,had_exam, had_quiz);
2335: break;
2336:
2337: case 'V': /* VIEW PREVIOUS SET */
2338: view_previous(student_number,set,§ion);
2339: display_menu(&a_student,had_exam, had_quiz);
2340: break;
2341:
2342: case 'S': /* DISPLAY TERM SUMMARY */
2343: configResult=read_capa_config("term_summary_button",buff);
2344: if (configResult != 0 && configResult != -1 ) {
2345: if ((strcasecmp(buff,"no")==0)) {
2346: break;
2347: }
2348: }
2349: term_summary(student_number,set,§ion,TERM_SUMMARY);
2350: display_menu(&a_student,had_exam, had_quiz);
2351: break;
2352: case 'E': /* VIEW EXAM SUMMARY */
2353: if( had_exam ) {
2354: chdir(Exam_path);
2355: term_summary(student_number,Exam_set,§ion,EXAM_SUMMARY);
2356: display_menu(&a_student,had_exam, had_quiz);
2357: chdir(Orig_path);
2358: }
2359: break;
2360: case 'Q': /* VIEW QUIZ SUMMARY */
2361: if( had_quiz ) {
2362: chdir(Quiz_path);
2363: term_summary(student_number,Quiz_set,§ion,QUIZ_SUMMARY);
2364: display_menu(&a_student,had_exam, had_quiz);
2365: chdir(Orig_path);
2366: }
2367: break;
2368: case EOF: /* EXIT SYSTEM */
2369: case 'X': ex=1; break;
2370:
2371: default: /* INVALID COMMAND */
2372: /* printf("Invalid choice\n"); */
2373: break;
2374: }
2375: }
2376: }
2377:
2378: /* -------------------------------------------------------------------------- */
2379: /* DISPLAY WELCOME MESSAGE WHEN USER LOGS IN */
2380: /* -------------------------------------------------------------------------- */
2381: void /* RETURNS: (nothing) */
2382: welcome() /* ARGUMENTS: */
2383: { /* LOCAL VARIABLES: */
2384: FILE *fp; /* Welcome file pointer */
2385: char buf[TMP_LINE_LENGTH]; /* Input buffer */
2386:
2387: CLEAR();
2388: /* sprintf(buf,"This is your %d-time login to this set, good luck!",tries);
2389: addstr(buf);
2390: */
2391: if ((fp=fopen("welcome.msg","r"))!=NULL) {
2392: while (fgets(buf,TMP_LINE_LENGTH-1,fp)) addstr(buf);
2393: fclose(fp);
2394: }
2395: }
2396:
2397: void print_version()
2398: {
2399: printf("capalogin\n");
2400: printf(" CAPA version %s, %s\n",CAPA_VER,COMPILE_DATE);
2401: }
2402:
2403: /* ------------------------------------------------------------------------- */
2404: /* DRIVER: INITIALIZE AND GO TO LOGIN */
2405: /* ------------------------------------------------------------------------- */
2406: int
2407: main(int argc, char **argv)
2408: { /* LOCAL VARIABLES: */
2409: char student_number[MAX_STUDENT_NUMBER+1]; /* Student number */
2410: int set, /* Set number */
2411: section=0, /* Section number */
2412: result; /* stores result from read_capa_config */
2413: char filename[FILE_NAME_LENGTH]; /* Question filename buffer */
2414: #if defined(NeXT)
2415: char cwd[FILE_NAME_LENGTH];
2416: #endif
2417: char *class_path, buf[MAX_BUFFER_SIZE],*tty;
2418:
2419:
2420: if (argc > 1) { if (strcmp(argv[1],"-v") == 0) {print_version(); exit(0); } }
2421: #ifdef LOGIN_DBUG
2422: printf("Create login.DBUG file:: argc = %d\n",argc);
2423: sprintf(filename,"login.DBUG");
2424: if ((dfp=fopen(filename,"a"))==NULL) { printf("Error: can't open login debug\n"); return; }
2425: #endif /* LOGIN_DBUG */
2426: /* GET CURRENT SET NUMBER */
2427: for(set = 1; ; set++ ) {
2428: sprintf(filename,"set%d.qz",set);
2429: if(capa_access(filename, F_OK) == -1 ) break;
2430: }
2431: set--;
2432: #if defined(NeXT)
2433: class_path = getwd(cwd);
2434: if( class_path == NULL ) class_path = cwd;
2435: #else
2436: class_path = getcwd(NULL,512);
2437:
2438: #endif
2439: sprintf(Orig_path,"%s",class_path);
2440: free(class_path);
2441: /* ---------------------------------------------- CURSES INITIALIZATION */
2442: signal(SIGINT , kick_out);
2443: signal(SIGALRM, kick_out);
2444: signal(SIGFPE, SIG_IGN);
2445: initscr(); savetty(); cbreak(); noecho();
2446: time(&log_in_time);
2447: strncpy(in_t,ctime(&log_in_time),31);
2448: in_t[ strlen(in_t)-1 ]=0; /* Trash newline */
2449: tty=ttyname(0);
2450: if ( tty == NULL ) {
2451: strcpy(in_tty,"UNKNOWN");
2452: } else {
2453: strcpy(in_tty,tty);
2454: }
2455: result=read_capa_config("capalogin_goodbye_delay",buf);
2456: if (result != 0 && result != -1) {
2457: g_delay=atoi(buf);
2458: } else {
2459: g_delay=5;
2460: }
2461: result=read_capa_config("capalogin_inactivity_delay",buf);
2462: if (result != 0 && result != -1) {
2463: g_max_delay=atoi(buf);
2464: } else {
2465: g_max_delay=60;
2466: }
2467: welcome();
2468: strcpy(student_number, login(&set,§ion)); student_number[MAX_STUDENT_NUMBER] = 0;
2469: #ifdef LOGIN_DBUG
2470: fprintf(dfp,"login return:SNum=%s, set=%d, sec=%d\n", student_number,set, section); fflush(dfp);
2471: #endif
2472: menu_main(student_number,set,section);
2473: #ifdef LOGIN_DBUG
2474: fclose(dfp);
2475: #endif
2476: properly_logout(student_number);
2477: return 0;
2478: }
2479:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>