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