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