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