Subversion Repositories wimsdev

Rev

Rev 17465 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. #include <utime.h>
  19. #include "wims.h"
  20.  
  21. /* Subroutines to process examinations */
  22.  
  23. char eparm[MAX_LINELEN+1];
  24.  
  25. void exam_parm(void)
  26. {
  27.   char *p1, *p2, *p3;
  28.   int v;
  29.   setvar("module_init_parm",eparm);
  30.   for(v=0,p1=eparm; *p1; p1=p2) {
  31.     while(*p1=='&') p1++;
  32.     p2=strchr(p1,'&');
  33.     if(p2==NULL) p2=p1+strlen(p1); else *p2++=0;
  34.     p3=strchr(p1,'='); if(p3==NULL) continue; else *p3++=0;
  35.     p1=find_word_start(p1); *find_word_end(p1)=0;
  36.     p3=find_word_start(p3); strip_trailing_spaces(p3);
  37.     user_variable[v].name=p1; user_variable[v].value=p3;
  38.     v++;
  39.   }
  40.   user_var_no=v;
  41. }
  42.  
  43. /* prepare examination situation */
  44. void check_exam(void)
  45. {
  46.   char *p, *p2, *e1, *e2, *pc=NULL;
  47.   char ps[64], pb[64], cbuf[64], dbuf[64], vbuf[MAX_FNAME+1];
  48.   int t1, t2;
  49.   int start, duration, remain;
  50.   double prime;
  51.   struct stat st;
  52.  
  53.   p=getvar(ro_name[ro_session]);
  54.   if(p==NULL || (p2=strstr(p,"_exam"))==NULL) return;
  55.   mystrncpy(pb,p,sizeof(pb)); p=pb;
  56.   p2=strstr(p,"_exam"); if(p2==NULL) return; else *p2=0;
  57.  
  58.   if(strchr(p2+1,'t')==NULL) {
  59.     e1=getvar(ro_name[ro_worksheet]);
  60.     if(e1==NULL || *e1==0) {
  61.       bad: user_error("bad_exam"); return;
  62.     }
  63.     e2=strchr(e1,'.'); if(e2==NULL) goto bad;
  64.     e2++; t1=atoi(e1); t2=atoi(e2);
  65.   }
  66.   else {
  67.     char *pt1,*pt2;
  68.     pt1=strchr(p2+1,'t'); pt2=strchr(pt1+1,'t');
  69.     *pt1++=0; *pt2++=0; t1=atoi(pt1); t2=atoi(pt2);
  70.   }
  71.   if(t1<1 || t1>99 || t2<1 || t2>99) goto bad;
  72.   snprintf(ps,sizeof(ps),"%s_examt%dt%d",p,t1,t2);
  73.   isexam=1; setsesdir(ps); force_setvar("wims_isexam","1");
  74.   force_setvar(ro_name[ro_session],ps);
  75.   /* get exam setup data */
  76.   accessfile(cbuf,"r","%s/%s/examdata.%d", session_dir,pb,t1);
  77.   if(cbuf[0]==0) goto bad;
  78.   p=find_word_start(cbuf); p2=find_word_end(p); if(*p2) *p2++=0;
  79.   duration=atoi(p)*60; if(duration==0) goto bad;
  80.   if(*p2) prime=atof(p2); else prime=0;
  81.   if (strstr(ps,parent_dir_string)!=NULL) user_error("wrong_session");
  82.   /* Whether the exercise is already done */
  83.   p=getvar(ro_name[ro_cmd]); if(p!=NULL) {
  84.     if(strcmp(p,"getins")==0 || strcmp(p,"getframe")==0) goto skipped;
  85.   }
  86.   exam_currscore(t1);
  87.   if(exam_scoredata[t2-1]!=-1000) {
  88.     snprintf(dbuf,sizeof(dbuf),"%.1f",exam_scoredata[t2-1]);
  89.     setvar("wims_exo_lastscore",dbuf);
  90.     /* Do we need to erase subsession? */
  91.     /* cannot see the page of the statement because of the user_error */
  92.     user_error("exam_exo_finished");
  93.   }
  94.   skipped:
  95.   snprintf(session_prefix,sizeof(session_prefix),"%s/%s",session_dir,ps);
  96.   snprintf(vbuf,sizeof(vbuf),"%s/var",session_prefix);
  97.   if(stat(vbuf,&st)==0) { /* exists */
  98.     unsetvar("module");
  99.     p=getvar(ro_name[ro_cmd]);
  100.     if(p==NULL) {
  101.       recmd:
  102.       force_setvar(ro_name[ro_cmd],commands[cmd_resume]);
  103.       user_var_no=0;
  104.     }
  105.     else {
  106.       int i;
  107.       for(i=0;i<CMD_NO && strcmp(p,commands[i]);i++);
  108.       if(i>=CMD_NO || i==cmd_intro || i==cmd_new || i==cmd_renew || i==cmd_hint)
  109.         goto recmd;
  110.     }
  111.   }
  112.   else { /* new */
  113.     char *pt, cbuf[MAX_FNAME+1], ebuf[MAX_FNAME+1];
  114.     char buf[2][MAX_LINELEN+1];
  115.     int w1,w2;
  116.  
  117.     force_setvar(ro_name[ro_cmd],commands[cmd_new]);
  118.     get_static_session_var();
  119.  
  120.     pc=getvar("wims_class"); if(pc==NULL) pc="";
  121.     snprintf(cbuf,sizeof(cbuf),"%s/%s",class_base,pc);
  122.     snprintf(ebuf,sizeof(ebuf),"%s/exams/.exam%d",cbuf,t1);
  123.     direct_datafile=1;
  124.     datafile_fnd_record(ebuf,t2,buf[0]);
  125.     direct_datafile=0;
  126.     if(buf[0][0]==0) goto bad;
  127.     fnd_line(buf[0],4,buf[1]);
  128.     if(buf[1][0]!=0) { /* dependencies */
  129.       if(!exam_depcheck(buf[1],t1)) {
  130.         user_error("exam_dep");
  131.       }
  132.     }
  133.     fnd_line(buf[0],2,buf[1]); if(buf[1][0]==0) goto bad;
  134.     calc_randitem(buf[1]);
  135.     pt=strchr(buf[1],'.');
  136.     if(pt==NULL) {
  137.       bad2: module_error("bad_exam_2"); return;
  138.     }
  139.     snprintf(exam_sheetexo,sizeof(exam_sheetexo),"      %s",buf[1]);
  140.     *pt++=0; w1=atoi(buf[1]); w2=atoi(pt);
  141.     if(w1<1 || w1>99 || w2<1 || w2>99) goto bad2;
  142.     snprintf(ebuf,sizeof(ebuf),"%s/sheets/.sheet%d",cbuf,w1);
  143.     direct_datafile=1;
  144.     datafile_fnd_record(ebuf,w2,buf[0]);
  145.     direct_datafile=0;
  146.     if(buf[0][0]==0) goto bad2;
  147.     fnd_line(buf[0],1,buf[1]); if(buf[1][0]==0) goto bad2;
  148.     force_setvar(ro_name[ro_module],buf[1]);
  149.     fnd_line(buf[0],2,eparm); /* if(eparm[0]==0) goto bad2; */
  150.     exam_parm();
  151.   }
  152.   get_static_session_var();
  153.  /* detect open exam in other session and forbidden open a new */
  154.   char *pu, pbuf1[MAX_LINELEN+1];
  155.   if(pc==NULL) pc=getvar("wims_class");
  156.   if(pc==NULL) pc="";
  157.   pu=getvar("wims_user"); if(pu==NULL) pu="";
  158.  /* line not needed at this step make directory is done later
  159.   snprintf(pbuf1,sizeof(pbuf1),"%s/%s/.parmreg", class_base, pc);
  160.   mkdirs(pbuf1);*/
  161.   snprintf(pbuf1,sizeof(pbuf1),"%s/%s/.parmreg/%s.exam",class_base, pc, pu);
  162.   if(stat(pbuf1,&st)==0) { /* search for other session ?? */
  163.     /* read file pbuf1 */
  164.     char pbuf2[MAX_LINELEN+1], *pf1, *pf2;
  165.     accessfile(pbuf2,"r",pbuf1);
  166.     pf1=find_word_start(find_word_end(find_word_start(pbuf2)));pf2=find_word_end(pf1);
  167.     memmove(pbuf2,pf1,pf2-pf1);pbuf2[pf2-pf1]=0;
  168.     if( strcmp(pbuf2,pb)!=0 && strcmp("supervisor",pu)!=0 ) { /* other exam session open */
  169.         user_error("other_exam_session"); return;
  170.     }
  171.   }
  172.   /* end of add for detect */
  173.  
  174.   /* Register start time */
  175.   snprintf(vbuf,sizeof(vbuf),"%s/%s/examreg.%d",
  176.         session_dir,pb,t1);
  177.   if(stat(vbuf,&st)==0) { /* reg exists */
  178.     char tbuf[MAX_LINELEN+1];
  179.     struct utimbuf ut;
  180.     accessfile(tbuf,"r",vbuf); start=atoi(tbuf);
  181.     if(start<=nowtime-duration) {
  182.       user_error("expired_exam"); return;
  183.     }
  184.     /* refresh session times */
  185.     ut.actime=ut.modtime=nowtime;
  186.     utime(mkfname(NULL,"%s/%s",session_dir,pb),&ut);
  187.   }
  188.   else { /* First time call: register starting time */
  189.     char *p1, tbuf[MAX_LINELEN+1];
  190.     snprintf(dbuf,sizeof(dbuf),"%u",(unsigned int) nowtime);
  191.     accessfile(dbuf,"w","%s",vbuf); start=nowtime;
  192. /*  variable initializing before
  193.     if(pc==NULL) pc=getvar("wims_class");
  194.     if(pc==NULL) pc="";
  195.     pu=getvar("wims_user"); if(pu==NULL) pu="";*/
  196.     snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg", class_base, pc);
  197.     mkdirs(vbuf);
  198.     snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg/%s.exam",
  199.          class_base, pc, pu);
  200.     p1=remote_addr;
  201.     snprintf(dbuf,sizeof(dbuf),"%s %s %u %d",
  202.          p1, pb, (unsigned int) start+duration, t1);
  203.     accessfile(dbuf,"w","%s",vbuf);
  204.     accessfile(tbuf,"r","%s/%s/.E%d",class_base,pc,t1);
  205.     if(strchr(tbuf,'#')==NULL && strcmp(pu,"supervisor")!=0) {  /* not for simulation */
  206.       snprintf(tbuf,sizeof(tbuf),"%d 00 %d %u %s %s %s\n",
  207.              t1, duration/60, (unsigned int) start,p1,pb,
  208.              nowstr);
  209.       if(prime!=0) {
  210.         int n=strlen(tbuf);
  211.           snprintf(tbuf+n,sizeof(tbuf)-n,"%d %.2f -1 %u %s %s\n",
  212.                 t1,prime,(unsigned int) start,p1,pb);
  213.       }
  214.       accessfile(tbuf,"a","%s/%s/score/%s.exam",
  215.                  class_base,pc,pu);
  216.     }
  217.     else accessfile("yes","w","%s/%s/examsimu.%d",
  218.           session_dir,pb,t1);
  219.   }
  220.   /* set up wims_scoring + wims_time_remain */
  221.   if(pc==NULL) pc=getvar("wims_class");
  222.   remain=duration+start-nowtime;
  223.   if(pc) {
  224.     int maxremain;
  225.     maxremain=getscorestatus(pc,t1);
  226.     /* negative return is score retriction timeleft */
  227.     if (maxremain<0 && -maxremain < remain) {
  228.       remain=-maxremain;
  229.     }
  230.     snprintf(vbuf,sizeof(vbuf),"%s/%s/examdepend.%d",session_dir,pb,t1);
  231.     snprintf(dbuf,sizeof(dbuf),"%u",(unsigned int) nowtime+remain);
  232.     accessfile(dbuf,"w","%s",vbuf);
  233.   }
  234.   if(remain<0) remain=0;
  235.   snprintf(dbuf,sizeof(dbuf),"%d",remain);
  236.   setvar("wims_exam_remain",dbuf);
  237. }
  238.  
  239. double currexamscore(int sh)
  240. {
  241.   char buf[MAX_FNAME+1], sbuf[MAX_LINELEN+1];
  242.   char *p, *p1, *cl;
  243.   int i, excnt;
  244.   double sc, w, ww, prime;
  245.  
  246.   cl=getvar("wims_class"); if(cl==NULL || *cl==0) return 0;
  247.   mystrncpy(sbuf,session_prefix,sizeof(sbuf));
  248.   p=strstr(sbuf,"_exam"); if(p) *p=0;
  249.   accessfile(buf,"r","%s/examdata.%d",sbuf,sh);
  250.   p=find_word_start(find_word_end(find_word_start(buf)));
  251.   if(*p) prime=atof(p); else prime=0;
  252.   exam_currscore(sh);
  253.   snprintf(buf,sizeof(buf),"%s/%s/exams/.exam%d",class_base,cl,sh);
  254.   direct_datafile=1;
  255.   excnt=datafile_recordnum(buf);
  256.   w=sc=0;
  257.   for(i=0;i<excnt;i++) {
  258.     sbuf[0]=0; datafile_fnd_record(buf,i+1,sbuf);
  259.     p1=find_word_start(sbuf); *find_word_end(p1)=0;
  260.     ww=atof(p1); if(ww<=0) continue;
  261.     w+=ww; if(exam_scoredata[i]>-1000) sc+=exam_scoredata[i]*ww;
  262.   }
  263.   direct_datafile=0; if(sc<0) sc=0;
  264.   if(w==0) return 0; else return (1-prime/10)*sc/w+prime;
  265. }
  266.  
  267. void calc_examdep(char *p)
  268. {
  269.   char *p1, *p2;
  270.   int t;
  271.   if(!trusted_module()) {abt: *p=0; return;}
  272.   p1=find_word_start(p); p2=find_word_end(p1);
  273.   if(*p2==0) goto abt;
  274.   *p2++=0; p2=find_word_start(p2);
  275.   t=atoi(p1);
  276.   snprintf(p,MAX_LINELEN, exam_depcheck(p2,t)? "yes" : "no");
  277. }
  278.