Annotation of capa/capa51/pProj/capalogin.c, revision 1.10
1.5 albertel 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
1.8 albertel 5: modify it under the terms of the GNU General Public License as
1.5 albertel 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
1.8 albertel 12: General Public License for more details.
1.5 albertel 13:
1.8 albertel 14: You should have received a copy of the GNU General Public
1.5 albertel 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,
1.6 albertel 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: */
1.5 albertel 24:
1.1 albertel 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 */
1.10 ! albertel 767: /*protect_log_string(log_string);*/
1.1 albertel 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 */
1.3 albertel 803: result,
804: tot_num_sets=0;
1.1 albertel 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;
1.3 albertel 823: if ( capa_check_date(CHECK_OPEN_DATE,student_number,*section,set_idx) < 0 )
824: continue;
825: tot_num_sets++;
1.1 albertel 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 */
1.3 albertel 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: }
1.1 albertel 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;
1.3 albertel 894: if ( capa_check_date(CHECK_OPEN_DATE,student_number,*section,set_idx) < 0 )
895: continue;
1.1 albertel 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:
1.2 albertel 1159: /*#define ANSWER_STRING_LENG 64*/
1.1 albertel 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;
1.4 albertel 1168: char *error=NULL;
1.1 albertel 1169:
1.4 albertel 1170: switch( capa_check_answers(p,a,cnt,&error) ) {
1.1 albertel 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;
1.4 albertel 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;
1.1 albertel 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;
1.4 albertel 1205: capa_mfree(error);
1.1 albertel 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;
1.4 albertel 1210: capa_mfree(error);
1.1 albertel 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;
1.4 albertel 1215: capa_mfree(error);
1.1 albertel 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];
1.4 albertel 1260: char *error=NULL;
1.1 albertel 1261:
1.4 albertel 1262: switch( capa_check_answers(p,a,cnt,&error) ) {
1.1 albertel 1263:
1264:
1265: case EXACT_ANS: *log_char='Y'; break;
1266: case APPROX_ANS: *log_char='Y'; break;
1.4 albertel 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;
1.1 albertel 1270: case NO_UNIT: *log_char='u'; break;
1271: case BAD_FORMULA:*log_char='F'; break;
1272: case INCORRECT: *log_char='N'; break;
1.4 albertel 1273: case WANTED_NUMERIC: *log_char='s'; break;
1.1 albertel 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;
1.10 ! albertel 1592: char date_str[DATE_LENGTH],*tmp;
1.1 albertel 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);
1.10 ! albertel 1618: tmp=strsave(answer);
! 1619: protect_log_string(tmp);
! 1620: sprintf(submissions_str,"%d\t%s\t",prob,tmp);
! 1621: capa_mfree(tmp);
1.1 albertel 1622: log_submissions(student_number,set,submissions_str);
1623: capa_mfree((char *)sbuf_pp);
1624: return 1;
1625: }
1626:
1627: void set_entry_tries(int *tried, char *tries, int num, int num_questions) {
1628: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1629: if(tried[num] < 10 ) {
1630: tries[3*num] = ' ';
1631: tries[3*num+1] = tried[num] + '0';
1632: if(num < num_questions-1) tries[3*num+2] = ',';
1633: } else {
1634: tries[3*num] = (int)(tried[num]/10) + '0';
1635: tries[3*num+1] = (tried[num] % 10) + '0';
1636: if(num < num_questions-1) tries[3*num+2] = ',';
1637: }
1638: } else {
1639: tries[3*num] = ' ';
1640: tries[3*num+1] = 1 + '0';
1641: if(num < num_questions-1) tries[3*num+2] = ',';
1642: }
1643: }
1644:
1645: /* -------------------------------------------------------------------------- */
1646: /* LET THE USER ANSWER THE CURRENT PROBLEM SET QUESTIONS */
1647: /* -------------------------------------------------------------------------- */
1648: void
1649: try_set(student_number,set,section)
1650: char *student_number;
1651: int set;
1652: int *section;
1653: {
1654: char a_student_number[MAX_STUDENT_NUMBER+1];
1655: time_t curtime;
1656: T_header header;
1657: Problem_t *first_problem, *p;
1658: T_entry entry;
1659: char answer[256], *a_str, **ans_strs;
1660: int num, offset, num_questions, start_from, leng;
1.10 ! albertel 1661: char *log_string,submissions_str[MAX_BUFFER_SIZE],*tmp;
1.1 albertel 1662: int *tried,answered;
1663: int scr_idx=1, display=1, second_scr, canAnswer;
1664: int usr_command, whereto, allow_hint=0, ex=0;
1665: char u_input[64], date_str[DATE_LENGTH], one_line[81];
1666: int log_char, i, j, allow_n, allow_p, allow_subj;
1667:
1668: strncpy(a_student_number,student_number,MAX_STUDENT_NUMBER+1);
1669: time(&curtime); /* Is due date past? */
1670: /* ---------------------------------------- check due date */
1671: #ifndef NO_DATE_CHECK
1672: /* ===> if ( compare_datetime(curtime,header.due_date) > 0) { */
1673: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1674: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1675: sprintf(answer," Sorry, the due date was: %s",date_str);
1676: move(17,1); clrtoeol(); mvaddstr(17,15,answer); mypause(19,17);
1677: return;
1678: }
1679: #ifdef LOGIN_DBUG
1680: fprintf(dfp,"Tryset():(sec=%d,set=%d)[%s]\n",*section,set,date_str); fflush(dfp);
1681: #endif /* LOGIN_DBUG */
1682: #endif /* NO_DATE_CHECK */
1683:
1684: offset=capa_get_entry(&entry,student_number,set);
1685: capa_get_header(&header,set);
1686: if (offset<0) offset = -offset; /* newly created entry */
1687:
1688: #ifdef LOGIN_DBUG
1689: fprintf(dfp,"P set=%d,SN=%s,ANS=%s,TRY=%s\n",set,a_student_number,entry.answers,entry.tries); fflush(dfp);
1690: #endif
1691: num = capa_parse(set,&first_problem,a_student_number,&num_questions,NULL);
1692:
1693: #ifdef LOGIN_DBUG
1694: fprintf(dfp,"ParseSource:=%d\n",num); fflush(dfp);
1695: #endif /* LOGIN_DBUG */
1696:
1697: /* DEBUGGING: make sure num_questions is plausible */
1698: if (num_questions>1000 || num_questions<=0) properly_logout(student_number);
1699:
1700: start_from=ask_what_prob(num_questions,entry.answers);
1701:
1702: /* initialize log string to all '-' */
1703: tried = (int *)capa_malloc(num_questions+1,sizeof(int));
1704: log_string = (char *)capa_malloc(num_questions+1,sizeof(char));
1705: for (num=0; num<num_questions; num++) {
1706: log_string[num]='-';
1707: sscanf(entry.tries + 3*num,"%d,",&(tried[num]) );
1708: }
1709: log_string[num_questions]=0;
1710: capa_set_login_time(student_number,set);
1711: for (num=0,p=first_problem; p; ){
1712: if( start_from > 1 ) {
1713: num=start_from-1;
1714: for (p=first_problem; start_from > 1 && p->next; start_from--)
1715: p=p->next;
1716: start_from = 0;
1717: }
1718: if (display) {
1719: /* DISPLAY QUESTION */
1720: CLEAR();
1721: second_scr = display_prob_scr(p->question,scr_idx);
1722: allow_subj = 0;
1723: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
1724: allow_subj = 1;
1725: move(A_ROW,A_COL); clrtoeol();
1726: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1727: }
1728: mvaddstr(S_ROW,0,"OPTION/ANSWER");
1729: mvaddstr(O_ROW,0,"Options :M = Main Menu :7 = go to # 7");
1730: allow_n = allow_p = 0;
1731: if( second_scr && (scr_idx == 1) ) {
1732: mvaddstr(O_ROW,E_COL,":N = Next screen");
1733: allow_n=1;
1734: }
1735: if( second_scr && (scr_idx == 2) ) {
1736: mvaddstr(O_ROW,E_COL,":P = Prev screen");
1737: allow_p=1;
1738: }
1739:
1740: mvaddstr(O_ROW,R_COL,"RETURN = Enter/Execute");
1741:
1742: if (g_inhibit_response ) {
1743: canAnswer = show_prior_inhibited_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1744: } else {
1745: canAnswer = show_prior_response(p,header.partial_credit[num],entry.answers[num],tried[num],&allow_hint);
1746: }
1747:
1748: }
1749: mvaddstr(X_ROW,X_COL,":X = eXit");
1750:
1751: /* <= */
1752:
1753:
1754:
1755: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1756: display=0; usr_command=C_DONTCARE;
1757: /* DEFAULT ACTIONS on empty input */
1758: if(!strlen(u_input)) { usr_command = (p->next? C_FORWARD : C_MENU); } else {
1759: if( u_input[0] == ':' ) {
1760: switch(toupper( u_input[1] )) {
1761: case 'H': if( allow_hint ) { usr_command=C_HINT; } break;
1762: case 'M': usr_command=C_MENU; break;
1763: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
1764: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
1765: case 'X': usr_command=C_EXIT; break;
1766: case 'A': if( allow_subj ) { usr_command=C_SUBJANS; } break;
1767: default : sscanf(u_input,":%d",&whereto);
1768: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
1769: break;
1770: }
1771: } else { /* user entered some answer */
1772: if( p->ans_op == ANS_AND ) {
1773: if(canAnswer) { usr_command=C_ANSWER;
1774: ans_strs = (char **)capa_malloc(sizeof(char *), p->ans_cnt);
1775: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1776: strcpy(ans_strs[0],u_input);
1777: for(i=1;i<p->ans_cnt;i++) {
1778: mvaddstr(A_ROW,A_COL," ");
1779: mvaddstr(A_ROW,A_COL,ans_strs[i-1]);
1780: sprintf(one_line, " Entering answer %3d of %3d ", i+1,p->ans_cnt);
1781: mvaddstr(A_ROW,S_COL,one_line);
1782: mvaddstr(S_ROW,A_COL," ");
1783: get_xinput(S_ROW,A_COL,u_input,U_ANS_CHAR);
1784: ans_strs[i] = (char *)capa_malloc(strlen(u_input)+1,1);
1785: strcpy(ans_strs[i],u_input);
1786:
1787: }
1788:
1789: /* now in ans_strs[][] are user inputs */
1790:
1791: }
1792: } else { /* one answer or ANS_OR */
1793: ans_strs = (char **)capa_malloc(sizeof(char *), 1);
1794: ans_strs[0] = (char *)capa_malloc(strlen(u_input)+1,1);
1795: strcpy(ans_strs[0], u_input);
1796: if(canAnswer) { usr_command=C_ANSWER;
1797: mvaddstr(S_ROW,A_COL," ");
1798: mvaddstr(A_ROW,A_COL," ");
1799: mvaddstr(A_ROW,A_COL,ans_strs[0]); }
1800: }
1801: } /* end if u_input[0] == ':' */
1802: } /* end if !strlen(u_input) */
1803:
1804:
1805:
1806:
1807:
1808: /* PROCESS USER COMMAND */
1809: switch(usr_command) {
1810: case C_FORWARD: /* Forwards */
1811: if (p->next) {
1812: p=p->next; num++;
1813: display=1; allow_hint=0; scr_idx=1;
1814: } else
1815: mvaddstr(X_ROW,R_COL,"RETURN = Main Menu ");
1816: break;
1817: case C_NEXTSCR: scr_idx = 2; display=1;
1818: break;
1819: case C_PREVSCR: scr_idx = 1; display=1;
1820: break;
1821: case C_EXIT: /* Exit */
1822: ex=1; p=0; break;
1823: case C_MENU: /* Return to main menu */
1824: p=0; break;
1825: case C_HINT: /* Hint */
1826: if (! p->hint) break;
1827: display_hint(p->hint);
1828: display=1;
1829: break;
1830: case C_ANSWER: /* Answer question */
1831: {
1832: if(p->ans_type== ANSWER_IS_SUBJECTIVE) {
1833: move(A_ROW,A_COL); clrtoeol();
1834: mvaddstr(A_ROW,A_COL,"Enter :A to answer subjective question");
1835: capa_mfree(ans_strs[0]);
1836: break;
1837: }
1838: if( p->ans_op == ANS_AND ) {
1839: leng = 0;
1840: for(i=0;i<p->ans_cnt;i++) {
1841: leng += (strlen((char *)ans_strs[i]) + 2);
1842: }
1843: a_str = (char *)capa_malloc(leng+1,1);
1844: a_str[0]=0;
1845: strcat(a_str,ans_strs[0]);
1846: if ( is_all_ws(ans_strs[0]) ) break;
1847: trim_response_ws(ans_strs[0]);
1848: for(i=1;i<p->ans_cnt;i++) {
1849: strcat(a_str,"\t");
1850: strcat(a_str,ans_strs[i]);
1851: if ( is_all_ws(ans_strs[i]) ) break;
1852: trim_response_ws(ans_strs[i]);
1853: }
1854: if (i < p->ans_cnt) {
1855: display=1; /*handle early breaks out of the*/
1856: break; /*loop which mean typed only ws */
1857: }
1858: } else { /* only one answer */
1859: leng = (strlen((char *)ans_strs[0]) + 2);
1860: a_str = (char *)capa_malloc(leng+1,1);
1861: a_str[0]=0;
1862: strcat(a_str,ans_strs[0]);
1863: if ( is_all_ws(ans_strs[0]) ) break;
1864: trim_response_ws(ans_strs[0]);
1865: }
1.10 ! albertel 1866: tmp=strsave(a_str);
! 1867: protect_log_string(tmp);
! 1868: sprintf(submissions_str,"%d\t%s\t",num+1,tmp);
! 1869: capa_mfree(tmp);
1.1 albertel 1870: log_submissions(student_number,set,submissions_str);
1871:
1872: {
1873: int cnt=((p->ans_op==ANS_AND)?p->ans_cnt:1);
1874: if (g_inhibit_response) {
1875: canAnswer = give_inhibited_response(p, ans_strs,cnt,
1876: &(tried[num]),&log_char);
1877: } else {
1878: canAnswer = give_response(p, ans_strs,cnt, &(tried[num]),&log_char);
1879: }
1880: }
1881: if( p->ans_op == ANS_AND ) {
1882: for(i=0;i<p->ans_cnt;i++) {
1883: capa_mfree( (char *)ans_strs[i] );
1884: }
1885:
1886: } else { /* there is only one user answer */
1887: capa_mfree( (char *)ans_strs[0] );
1888:
1889: }
1890: capa_mfree((char *)ans_strs);
1891: capa_mfree( (char *)a_str );
1892:
1893: if (p->hint &&
1894: (
1895: (p->show_hint<=tried[num])||
1896: (log_char == 'y') ||
1897: (log_char == 'Y')
1898: )
1899: ){
1900: allow_hint=1;
1901: mvaddstr(X_ROW,H_COL,":H = Show Hint");
1902: }
1903: switch(log_char) {
1.2 albertel 1904: case 'U': case 'u': case 'S': case 'F':
1.1 albertel 1905: entry.answers[num]='N'; break;
1906: case 'Y': allow_hint=1; mvaddstr(X_ROW,H_COL,":H = Show Hint"); /* fall through here */
1907: default: entry.answers[num]=log_char; break;
1908: }
1909: log_string[num]=log_char;
1910:
1911: log_attempt(student_number,set,*section,log_string);
1912: /* for (i=0; i<num_questions; i++) { log_string[i] = '-' ; } */
1913: set_entry_tries(tried,entry.tries,num,num_questions);
1914: log_string[num]='-';
1915: /* ------------------------------ check due date */
1916: time(&curtime);
1917: /* ===> if (compare_datetime(curtime,header.due_date) > 0) { */
1.9 albertel 1918: #ifndef NO_DATE_CHECK
1.1 albertel 1919: if( capa_check_date(CHECK_DUE_DATE,student_number,*section,set) > 0 ) {
1920: capa_get_date(CHECK_DUE_DATE,student_number,*section,set,date_str);
1921: sprintf(answer,"Sorry, the due date was: %s",date_str);
1922: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1.9 albertel 1923: } else
1924: #endif
1925: {
1.1 albertel 1926: capa_set_entry(&entry,student_number,set,offset);
1927: }
1928: } break;
1929: case C_JUMP: /* Jump to specific question number */
1930: num=whereto-1;
1931: for (p=first_problem; whereto > 1 && p->next; whereto--)
1932: p=p->next;
1933: display=1; allow_hint=0; scr_idx=1;
1934: break;
1935: case C_SUBJANS:
1936: answered=answer_subjective(student_number,set,section,num+1);
1937: if (answered) {
1938: tried[num]++;
1939: if (p->hint && ((p->show_hint<=tried[num]))) { allow_hint=1; }
1940: entry.answers[num]='0';
1941: log_string[num]='A';
1942: log_attempt(student_number,set,*section,log_string);
1943: log_string[num]='-';
1944: set_entry_tries(tried,entry.tries,num,num_questions);
1945: capa_set_entry(&entry,student_number,set,offset);
1946: }
1947: display=1;
1948: break;
1949: case C_DONTCARE: break;
1950: }
1951: }
1952: for (i=0,j=0, num=0; num<num_questions; num++) {
1953: j = j + (header.weight[num] - '0');
1954: if((entry.answers[num]=='Y') || (entry.answers[num]=='y'))
1955: i = i + (header.weight[num] - '0');
1956: if( entry.answers[num] >= '0' && entry.answers[num] <= '9' ) {
1957: i = i + (entry.answers[num] - '0');
1958: }
1959: if((entry.answers[num]=='E') || (entry.answers[num]=='e'))
1960: j = j - (header.weight[num] - '0');
1961: if((tried[num] >=0) && (tried[num] <= TRY_BOUND) ) {
1962: if(tried[num] < 10 ) {
1963: entry.tries[3*num] = ' ';
1964: entry.tries[3*num+1] = tried[num] + '0';
1965: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1966: } else {
1967: entry.tries[3*num] = (int)(tried[num]/10) + '0';
1968: entry.tries[3*num+1] = (tried[num] % 10) + '0';
1969: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1970: }
1971: } else {
1972: entry.tries[3*num] = ' ';
1973: entry.tries[3*num+1] = 1 + '0';
1974: if(num < num_questions-1) entry.tries[3*num+2] = ',';
1975: }
1976: }
1977: capa_mfree(header.weight);
1978: capa_mfree(header.partial_credit);
1979:
1980: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1981: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1982: /* ------- original code , should check due date before save it
1983:
1984: time(&curtime);
1985: if (compare_datetime(curtime,header.due_date) > 0) {
1986: if( capa_check_date(CHECK_DUE_DATE,*section,set) > 0 ) {
1987: need to deal with due_date
1988: sprintf(answer,"Sorry, the due date was: %s",header.due_date);
1989: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1990: } else {
1991: sprintf(answer,"Your score for this set is now: %d/%d",i,j);
1992: move(20,1); clrtobot(); addstr(answer); mypause(23,1);
1993:
1994: capa_set_entry(&entry,student_number,set,offset);
1995: }
1996: ------ */
1997: /* FREE UP MALLOC'ED SPACE (VERY IMPORTANT) */
1998: capa_mfree(entry.answers);
1999: capa_mfree(entry.tries);
2000: free_problems(first_problem);
2001: /* log_attempt(student_number,set,*section,log_string); */
2002: capa_mfree(log_string);
2003: capa_mfree((char*)tried);
2004: if (ex) properly_logout(student_number);
2005:
2006: }
2007:
2008: #define COL_ONE 1
2009: #define COL_TWO 17
2010: #define COL_THREE 34
2011: #define COL_FOUR 43
2012: #define COL_FIVE 69
2013:
2014: /* ------------------------------------------------------------------------- */
2015: /* REVIEW PREVIOUS PROBLEM SETS */
2016: /* ------------------------------------------------------------------------- */
2017: void /* RETURNS: (nothing) */
2018: view_previous(student_number,set,section) /* ARGUMENTS: */
2019: char *student_number; /* Student number */
2020: int set; /* Set number */
2021: int *section; /* Section number */
2022: { /* LOCAL VARIABLES: */
2023: T_entry entry; /* Database entry */
2024: Problem_t *first_problem, /* Pointer to first problem */
2025: *problem; /* Previous problem */
2026: int num_questions, /* Total # of questions */
2027: ex=0, /* Exit system flag */
2028: display=1, /* Redraw flag */
2029: usr_command,
2030: whereto,
2031: allow_hint=0, allow_explain=0;
2032: int num; /* Temporary variable */
2033: char buf[4], /* Command input buffer */
2034: aLine[MAX_BUFFER_SIZE];
2035: T_header header; /* Set header */
2036: time_t curtime; /* Current time */
2037: double upper_ans;
2038: char fmt_ans[ANSWER_STRING_LENG], goto_str[ANSWER_STRING_LENG],
2039: tmp_str[ANSWER_STRING_LENG];
2040: int scr_idx=1, second_scr, allow_n, allow_p;
2041:
2042: /* QUERY USER FOR SET */
2043: move(15,5); /* deleteln(); */
2044: addstr(" Which set would you like to view?");
2045: mvaddstr(16,15, "Enter a set number and press ENTER/RETURN");
2046: move(17,1); clrtoeol(); /* erase Enter a command ... */
2047: do { get_input(15,51,buf,3); } while(!strlen(buf));
2048: sscanf(buf,"%d",&num);
2049: if (num<1 || num>set) {
2050: move(17,5); clrtoeol();
2051: mvaddstr(17,15," Error: Invalid previous set number\n");
2052: mypause(19,17); return;
2053: }
2054: /* ------------------------------------ answer date */
2055: time(&curtime);
2056: /* ===> if (compare_datetime(curtime,header.answer_date) < 0) { */
2057: if ( capa_check_date(CHECK_ANS_DATE,student_number,*section,num) < 0 ) {
2058: move(16,1); clrtoeol();
2059: move(17,5); clrtoeol();
2060: mvaddstr(17,15," Answers are not yet available\n"); mypause(19,17); return;
2061: }
2062:
2063: /* LOAD IN THE INFO NEEDED */
2064: capa_get_header(&header,num);
2065: capa_get_entry(&entry,student_number,num);
2066: capa_parse(num,&first_problem,student_number,&num_questions,NULL);
2067: sprintf(goto_str,"#=go to problem #, [%d problems]", num_questions);
2068: for (num=0,problem=first_problem; problem; ) {
2069: if (display) {
2070: allow_hint = allow_explain=0;
2071: allow_n = allow_p = 0;
2072: CLEAR();
2073: second_scr = display_prob_scr(problem->question,scr_idx);
2074: if( problem->ans_type == ANSWER_IS_FLOAT ) {
2075: upper_ans = (double)atof(problem->answer);
2076: sprintf(fmt_ans, problem->ans_fmt, upper_ans);
2077: } else {
2078: sprintf(fmt_ans, "%s", problem->answer);
2079: }
2080: if( problem->ans_unit ) {
2081: sprintf(tmp_str, "Answer: %s %s",fmt_ans,problem->unit_str);
2082: } else {
2083: sprintf(tmp_str, "Answer: %s",fmt_ans);
2084: }
2085: mvaddstr(S_ROW,COL_ONE,tmp_str);
2086:
2087: switch(entry.answers[num]) {
2088: case 'Y': mvaddstr(S_ROW,COL_FOUR,"CORRECT "); break;
2089: case 'y': mvaddstr(S_ROW,COL_FOUR,"HANDIN CORRECT "); break;
2090: case '-': mvaddstr(S_ROW,COL_FOUR,"UNANSWERED "); break;
2091: case 'e': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2092: case 'E': mvaddstr(S_ROW,COL_FOUR,"EXCUSED "); break;
2093: case 'n': mvaddstr(S_ROW,COL_FOUR,"HANDIN INCORRECT"); break;
2094: case 'N': mvaddstr(S_ROW,COL_FOUR,"INCORRECT "); break;
2095: default : if(entry.answers[num] >= '0' && entry.answers[num] <= '9') {
2096: sprintf(aLine,"HAND-GRADED %c/%c ",entry.answers[num],
2097: header.weight[num]);
2098: mvaddstr(S_ROW,COL_FOUR,aLine);
2099: }
2100: break;
2101: }
2102: mvaddstr(S_ROW,COL_FIVE,"OPTION:");
2103:
2104: mvaddstr(O_ROW,COL_ONE,"M=Main menu");
2105: if( second_scr && scr_idx == 1) {
2106: mvaddstr(O_ROW,COL_TWO,"N=Next screen");
2107: allow_n = 1;
2108: }
2109: if( second_scr && scr_idx == 2) {
2110: mvaddstr(O_ROW,COL_TWO,"P=Prev screen");
2111: allow_p = 1;
2112: }
2113: mvaddstr(O_ROW,COL_THREE,"X=eXit");
2114: mvaddstr(O_ROW,COL_FOUR, "RETURN=Enter/Execute");
2115: if ( problem->hint &&
2116: (
2117: (problem->show_hint <= problem->tries) ||
2118: (entry.answers[num] == 'Y') ||
2119: (entry.answers[num] == 'y')
2120: )
2121: ) {
2122: allow_hint=1; mvaddstr(O_ROW,COL_FIVE,"H=Hint");
2123: }
2124: mvaddstr(X_ROW,COL_ONE,goto_str);
2125: if (problem->next)
2126: mvaddstr(X_ROW,COL_FOUR,"RETURN=next problem");
2127: else
2128: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2129: if ( problem->explain ) { allow_explain=1; mvaddstr(X_ROW,COL_FIVE,"E=Explain"); }
2130:
2131: }
2132: get_input(S_ROW,COL_FIVE+7,buf,3);
2133: display=0; usr_command=C_DONTCARE;
2134: /* DEFAULT ACTIONS on empty input */
2135: if(!strlen(buf)) { usr_command = (problem->next? C_FORWARD : C_MENU); } else {
2136: switch(toupper(buf[0])) {
2137: case 'X': usr_command=C_EXIT; break;
2138: case 'M': usr_command=C_MENU; break;
2139: case 'H': usr_command=C_HINT; break;
2140: case 'E': usr_command=C_EXPLAIN; break;
2141: case 'N': if( allow_n ) { usr_command=C_NEXTSCR; } break;
2142: case 'P': if( allow_p ) { usr_command=C_PREVSCR; } break;
2143: default : sscanf(buf,"%d",&whereto);
2144: if(whereto >0 && whereto <= num_questions) usr_command=C_JUMP;
2145: break;
2146: }
2147: }
2148:
2149:
2150: /* PROCESS USER COMMAND */
2151: switch(usr_command) {
2152: case C_FORWARD: /* FORWARDS ONE */
2153: if (problem->next) {
2154: problem=problem->next; display=1; scr_idx = 1; num++;
2155: } else
2156: mvaddstr(X_ROW,COL_FOUR,"RETURN=main menu ");
2157: break;
2158: case C_HINT: /* HINT */
2159: if(allow_hint) {
2160: display_hint(problem->hint);
2161: display=1;
2162: allow_hint = 0;
2163: }
2164: break;
2165: case C_EXPLAIN: /* Explain */
2166: if(allow_explain) {
2167: display_hint(problem->explain); display=1;
2168: allow_explain=0;
2169: }
2170: break;
2171: case C_NEXTSCR: scr_idx = 2; display=1;
2172: break;
2173: case C_PREVSCR: scr_idx = 1; display=1;
2174: break;
2175: case C_EXIT: /* EXIT SYSTEM */
2176: ex=1; problem=0; break;
2177:
2178: case C_MENU: /* RETURN TO MAIN MENU */
2179: problem=0; break;
2180:
2181: case C_JUMP: /* JUMP TO SPECIFIC PROBLEM # */
2182: num=whereto-1;
2183: for (problem=first_problem; whereto > 1 && problem->next; whereto--)
2184: problem=problem->next;
2185: display=1;
2186: scr_idx = 1;
2187: break;
2188: case C_TIME: break;
2189: case C_DONTCARE: break;
2190: }
2191: }
2192:
2193: /* FREE UP MALLOC'ED SPACE - VERY IMPORTANT */
2194: capa_mfree(header.weight);
2195: capa_mfree(header.partial_credit);
2196: capa_mfree(entry.answers);
2197: capa_mfree(entry.tries);
2198: free_problems(first_problem);
2199:
2200: if (ex) properly_logout(student_number);
2201: }
2202:
2203: /* -------------------------------------------------------------------------- */
2204: /* DISPLAY HELP SCREEN */
2205: /* -------------------------------------------------------------------------- */
2206: void /* RETURNS: (nothing) */
2207: display_help() /* ARGUMENTS: (none) */
2208: { /* LOCAL VARIABLES: */
2209: FILE *fp; /* Welcome file pointer */
2210: char buf[255]; /* Input buffer */
2211:
2212: CLEAR();
2213: if ((fp=fopen("help.msg","r"))!=NULL) {
2214: while (fgets(buf,255,fp)) addstr(buf);
2215: fclose(fp);
2216: }
2217: mypause(22,20);
2218: }
2219:
2220:
2221: /* A class directory must have */
2222: /* records/ */
2223: /* */
2224: /* returns: 0 structure is correct, but no set.db files */
2225: /* -1 structure is not correct */
2226: /* >=1 the last set.db */
2227:
2228: int
2229: check_class_get_set(dir_path) char *dir_path;
2230: {
2231: char f_name[1024];
2232: int set;
2233:
2234: if( capa_access(dir_path, F_OK) == 0 ) { /* class dir exists */
2235: sprintf(f_name,"%s/records",dir_path);
2236: if( capa_access(f_name, F_OK) == 0 ) { /* class/records dir exists */
2237: for(set = 1; ; set++ ) {
2238: sprintf(f_name,"%s/records/set%d.db",dir_path,set);
2239: if(capa_access(f_name, F_OK) == -1 ) break;
2240: }
2241: set--;
2242: } else {
2243: set = -1;
2244: }
2245: } else {
2246: set = -1;
2247: }
2248: return (set);
2249: }
2250: /* -------------------------------------------------------------------------- */
2251: /* Get Exam and Quiz Path */
2252: /* return 0, 1, 2, 3 */
2253: /* -------------------------------------------------------------------------- */
2254: int
2255: check_exam_quiz_f()
2256: {
2257: char buf[MAX_BUFFER_SIZE];
2258: int result = 0, configResult=0;
2259:
2260: #ifdef LOGIN_DBUG
2261: fprintf(dfp,"CHECK EXAM Access() success,and open(),%s\n",buf); fflush(dfp);
2262: #endif
2263: configResult=read_capa_config("exam_path",buf);
2264: if (configResult != 0 && configResult != -1) {
2265: Exam_set = check_class_get_set(buf);
2266: if(Exam_set > 0 ) {
2267: result = 1;
2268: sprintf(Exam_path,buf);
2269: }
2270: }
2271: #ifdef LOGIN_DBUG
2272: fprintf(dfp,"CHECK EXAM = %d,%s\n", result,Exam_path); fflush(dfp);
2273: #endif
2274: configResult=read_capa_config("quiz_path",buf);
2275: if (configResult != 0 && configResult != -1) {
2276: Quiz_set = check_class_get_set(buf);
2277: if(Quiz_set > 0 ) {
2278: result = (result | 2);
2279: sprintf(Quiz_path,buf);
2280: }
2281: }
2282:
2283: return (result);
2284: }
2285:
2286: /* -------------------------------------------------------------------------- */
2287: /* DISPLAY MAIN MENU */
2288: /* -------------------------------------------------------------------------- */
2289: void /* RETURNS: (nothing) */
2290: display_menu(student, exam_f, quiz_f)
2291: T_student *student;
2292: int exam_f, quiz_f;
2293: {
2294: char buff[MAX_BUFFER_SIZE];
2295: int c_y,configResult,term_summary_button=1;
2296:
2297: configResult=read_capa_config("term_summary_button",buff);
2298: if (configResult != 0 && configResult != -1 ) {
2299: if (strcasecmp(buff,"no")==0) {
2300: term_summary_button=0;
2301: }
2302: }
2303:
2304: CLEAR();
2305:
2306: mvaddstr(1,10,student->s_nm);
2307: sprintf(buff,"Section: %d",student->s_sec);
2308: mvaddstr(1,50,buff);
2309:
2310: mvaddstr( 4,25," MAIN MENU"); c_y = 6;
2311: mvaddstr( c_y,25,"H=Help"); c_y++;
2312: if (term_summary_button) { mvaddstr( c_y,25,"S=Summary"); c_y++; }
2313: mvaddstr( c_y,25,"T=Try set"); c_y++;
2314: mvaddstr( c_y,25,"V=View previous set"); c_y++;
2315: if(exam_f) { mvaddstr( c_y,25,"E=view Exam summary"); c_y++; }
2316: if(quiz_f) { mvaddstr( c_y,25,"Q=view Quiz summary"); c_y++; }
2317: mvaddstr( c_y,25,"X=eXit system");
2318:
2319: mvaddstr(14,25,"COMMAND:");
2320:
2321: mvaddstr(17, 5,"Enter a command from the list above and press ENTER/RETURN");
2322: }
2323:
2324: /* -------------------------------------------------------------------------- */
2325: /* CONTROL MAIN MENU SELECTIONS */
2326: /* -------------------------------------------------------------------------- */
2327: void /* RETURNS: (nothing) */
2328: menu_main(student_number,set,section) /* ARGUMENTS: */
2329: char *student_number; /* Student number */
2330: int set; /* Set number */
2331: int section; /* Section number */
2332: { /* LOCAL VARIABLES: */
2333: int ex=0, /* Exit system flag */
2334: cmd; /* User command */
2335: char buff[MAX_BUFFER_SIZE]; /* User command buffer */
2336: T_student a_student;
2337: int had_exam, had_quiz, outcome,configResult;
2338:
2339: #ifdef LOGIN_DBUG
2340: fprintf(dfp,"MENU in %s sec=%d\n", student_number,section); fflush(dfp);
2341: #endif
2342:
2343: outcome = check_exam_quiz_f();
2344: had_exam = outcome & 1;
2345: had_quiz = outcome & 2;
2346:
2347: #ifdef LOGIN_DBUG
2348: fprintf(dfp,"After check %d\n", outcome); fflush(dfp);
2349: #endif
2350:
2351: capa_get_student(student_number,&a_student);
2352:
2353: g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set,section);
2354: if (g_inhibit_response < 0 ) g_inhibit_response=0;
2355:
2356: display_menu(&a_student,had_exam, had_quiz);
2357: while (!ex) {
2358: do {
2359: buff[0] = ' '; buff[1] = 0;
2360: get_input(14,34,buff,1); cmd=toupper(buff[0]);
2361: } while (isspace(cmd));
2362: move(14,35); clrtoeol();
2363: /* PROCESS USER COMMAND */
2364: switch(cmd) {
2365:
2366: case 'H': /* DISPLAY HELP */
2367: display_help();
2368: display_menu(&a_student,had_exam, had_quiz);
2369: break;
2370:
2371: case 'T': /* TRY CURRENT SET */
2372: try_set(student_number,set,§ion);
2373: display_menu(&a_student,had_exam, had_quiz);
2374: break;
2375:
2376: case 'V': /* VIEW PREVIOUS SET */
2377: view_previous(student_number,set,§ion);
2378: display_menu(&a_student,had_exam, had_quiz);
2379: break;
2380:
2381: case 'S': /* DISPLAY TERM SUMMARY */
2382: configResult=read_capa_config("term_summary_button",buff);
2383: if (configResult != 0 && configResult != -1 ) {
2384: if ((strcasecmp(buff,"no")==0)) {
2385: break;
2386: }
2387: }
2388: term_summary(student_number,set,§ion,TERM_SUMMARY);
2389: display_menu(&a_student,had_exam, had_quiz);
2390: break;
2391: case 'E': /* VIEW EXAM SUMMARY */
2392: if( had_exam ) {
2393: chdir(Exam_path);
2394: term_summary(student_number,Exam_set,§ion,EXAM_SUMMARY);
2395: display_menu(&a_student,had_exam, had_quiz);
2396: chdir(Orig_path);
2397: }
2398: break;
2399: case 'Q': /* VIEW QUIZ SUMMARY */
2400: if( had_quiz ) {
2401: chdir(Quiz_path);
2402: term_summary(student_number,Quiz_set,§ion,QUIZ_SUMMARY);
2403: display_menu(&a_student,had_exam, had_quiz);
2404: chdir(Orig_path);
2405: }
2406: break;
2407: case EOF: /* EXIT SYSTEM */
2408: case 'X': ex=1; break;
2409:
2410: default: /* INVALID COMMAND */
2411: /* printf("Invalid choice\n"); */
2412: break;
2413: }
2414: }
2415: }
2416:
2417: /* -------------------------------------------------------------------------- */
2418: /* DISPLAY WELCOME MESSAGE WHEN USER LOGS IN */
2419: /* -------------------------------------------------------------------------- */
2420: void /* RETURNS: (nothing) */
2421: welcome() /* ARGUMENTS: */
2422: { /* LOCAL VARIABLES: */
2423: FILE *fp; /* Welcome file pointer */
2424: char buf[TMP_LINE_LENGTH]; /* Input buffer */
2425:
2426: CLEAR();
2427: /* sprintf(buf,"This is your %d-time login to this set, good luck!",tries);
2428: addstr(buf);
2429: */
2430: if ((fp=fopen("welcome.msg","r"))!=NULL) {
2431: while (fgets(buf,TMP_LINE_LENGTH-1,fp)) addstr(buf);
2432: fclose(fp);
2433: }
2434: }
2435:
2436: void print_version()
2437: {
2438: printf("capalogin\n");
2439: printf(" CAPA version %s, %s\n",CAPA_VER,COMPILE_DATE);
1.7 albertel 2440: printf(" CAPA is released under the GNU GPL v2 see COPYING for details.\n");
1.1 albertel 2441: }
2442:
2443: /* ------------------------------------------------------------------------- */
2444: /* DRIVER: INITIALIZE AND GO TO LOGIN */
2445: /* ------------------------------------------------------------------------- */
2446: int
2447: main(int argc, char **argv)
2448: { /* LOCAL VARIABLES: */
2449: char student_number[MAX_STUDENT_NUMBER+1]; /* Student number */
2450: int set, /* Set number */
2451: section=0, /* Section number */
2452: result; /* stores result from read_capa_config */
2453: char filename[FILE_NAME_LENGTH]; /* Question filename buffer */
2454: #if defined(NeXT)
2455: char cwd[FILE_NAME_LENGTH];
2456: #endif
2457: char *class_path, buf[MAX_BUFFER_SIZE],*tty;
2458:
2459:
2460: if (argc > 1) { if (strcmp(argv[1],"-v") == 0) {print_version(); exit(0); } }
2461: #ifdef LOGIN_DBUG
2462: printf("Create login.DBUG file:: argc = %d\n",argc);
2463: sprintf(filename,"login.DBUG");
2464: if ((dfp=fopen(filename,"a"))==NULL) { printf("Error: can't open login debug\n"); return; }
2465: #endif /* LOGIN_DBUG */
2466: /* GET CURRENT SET NUMBER */
2467: for(set = 1; ; set++ ) {
2468: sprintf(filename,"set%d.qz",set);
2469: if(capa_access(filename, F_OK) == -1 ) break;
2470: }
2471: set--;
2472: #if defined(NeXT)
2473: class_path = getwd(cwd);
2474: if( class_path == NULL ) class_path = cwd;
2475: #else
2476: class_path = getcwd(NULL,512);
2477:
2478: #endif
2479: sprintf(Orig_path,"%s",class_path);
2480: free(class_path);
2481: /* ---------------------------------------------- CURSES INITIALIZATION */
2482: signal(SIGINT , kick_out);
2483: signal(SIGALRM, kick_out);
2484: signal(SIGFPE, SIG_IGN);
2485: initscr(); savetty(); cbreak(); noecho();
2486: time(&log_in_time);
2487: strncpy(in_t,ctime(&log_in_time),31);
2488: in_t[ strlen(in_t)-1 ]=0; /* Trash newline */
2489: tty=ttyname(0);
2490: if ( tty == NULL ) {
2491: strcpy(in_tty,"UNKNOWN");
2492: } else {
2493: strcpy(in_tty,tty);
2494: }
2495: result=read_capa_config("capalogin_goodbye_delay",buf);
2496: if (result != 0 && result != -1) {
2497: g_delay=atoi(buf);
2498: } else {
2499: g_delay=5;
2500: }
2501: result=read_capa_config("capalogin_inactivity_delay",buf);
2502: if (result != 0 && result != -1) {
2503: g_max_delay=atoi(buf);
2504: } else {
2505: g_max_delay=60;
2506: }
2507: welcome();
2508: strcpy(student_number, login(&set,§ion)); student_number[MAX_STUDENT_NUMBER] = 0;
2509: #ifdef LOGIN_DBUG
2510: fprintf(dfp,"login return:SNum=%s, set=%d, sec=%d\n", student_number,set, section); fflush(dfp);
2511: #endif
2512: menu_main(student_number,set,section);
2513: #ifdef LOGIN_DBUG
2514: fclose(dfp);
2515: #endif
2516: properly_logout(student_number);
2517: return 0;
2518: }
2519:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>