/* Programa de correccion de examenes. Necesita subrutinas en ensamblador para gestionar las interrupciones de la puerta serial. Escrito para funcionar con una lectora Kaiser OMR-15 Version 1.00 -- (C) Fernando TUSELL, 19-Junio-1.989 */ #include "stdio.h" /*------------------------------------------------------------------------- DECLARACION DE VARIABLES, PARAMETROS Y FUNCIONES EXTERNAS --------------------------------------------------------------------------*/ #define buf_len 16384 /* Longitud buffer */ #define fold 15184 /* Longitud tras de la cual un fin de documento provoca el recomienzo */ #define long_ex 505 /* Longitud examen + 1 */ #define long_lin 12 /* Longitud linea; long_ex=42*long_lin +1 */ #define hextodec(x) ((('0'<= x) && ( x <='9')) ? (x - '0') : (x-55)) #define min(A,B) ((A) < (B) ? (A) : (B) ) #define pliega if (i<= fold) asc_out[0]++; else asc_out[0] = 0; int beg, /* Comienzo en asc_buf[] de un examen */ bien, blanco, mal, punt[9][120],/* Puntos de las distintas preguntas */ result, /* Resultado llamada a funciones */ numexam, /* Numero de tipos de examen diferentes */ numpreg; /* Numero de preguntas (comun a todos los examenes) */ double puntos = 0.0, penal = 0.0; char dni[9], anex[5], tipex, expe[6], acierto[121];/* 1 para pregunta bien, 0 para pregunta mal */ unsigned char resp[9][120];/* Respuestas a las distintas preguntas */ extern int cls(), /* Subrutina limpieza pantalla */ asc_enb(), /* Captura interrupcion puerta serial COM1: */ asc_dsb(), /* Restauracion vector interrupciones */ asc_int(); /* Servicio interrupcion puerta serial */ extern char asc_buf[]; /* Buffer circular (de 16384) de recepcion de caracteres procedentes de la lectora. */ extern unsigned asc_in[], /* Lugar del buffer para proximo caracter */ asc_out[]; /* Lugar del buffer con el primer caracter a leer */ FILE *ptr; struct regval {int ax,bx,cx,dx,si,di,ds,es;}; /* FUNCIONES STANDARD DE LIBRERIA COMPILADOR C */ extern char fgets(); extern int crt_srcp(), crt_mode(), exit(), fputs(); pide_inst() { struct regval call_regs, ret_regs; call_regs.ax = 0x0800; sysint(0x21,&call_regs,&ret_regs); return((ret_regs.ax & 0x00FF)); }; termina() { crt_srcp(15,0,0); fputs("Programa terminado sin incidencias.",stdout); fclose(ptr); asc_dsb(); exit(0); }; wait_char() { struct regval call_regs, ret_regs; call_regs.ax = 0x0b00; sysint(0x21,&call_regs,&ret_regs); return((0x00FF == (ret_regs.ax & 0x00FF))); }; identifi(beg) { int i, j, k, now; char e, digit; unsigned char d; extern char dni[],expe[],tipex,anex[],asc_buf[]; if(asc_buf[beg] != '@') {fputs(" Ha habido algun problema en la lectura\n",stdout);} strncpy(dni,"????????\0",9); strncpy(expe,"?????\0",6); tipex = '?'; strncpy(anex,"???\0",4); k = long_lin + 4; for(i=0;i<=9;i++) { digit = '0' + i; now = beg + k; d = asc_buf[now] - '0'; /* El segundo nibble del primer byte es siempre un digito entre 0 y 7 */ if(0x04 == (0x04 & d)) dni[0] = digit; if(0x02 == (0x02 & d)) dni[1] = digit; if(0x01 == (0x01 & d)) dni[2] = digit; e = asc_buf[++now]; /* Ahora en cambio si nos hemos de */ d = hextodec(e); /* preocupar de si tenemos un digito */ /* hexadecimal mayor o menor que 'A' */ if(0x08 == (0x08 & d)) dni[3] = digit; if(0x04 == (0x04 & d)) dni[4] = digit; if(0x02 == (0x02 & d)) dni[5] = digit; if(0x01 == (0x01 & d)) dni[6] = digit; e = asc_buf[++now]; d = hextodec(e); if(0x08 == (0x08 & d)) dni[7] = digit; if(0x02 == (0x02 & d)) expe[0] = digit; if(0x01 == (0x01 & d)) expe[1] = digit; e = asc_buf[++now]; d = hextodec(e); if(0x08 == (0x08 & d)) expe[2] = digit; if(0x04 == (0x04 & d)) expe[3] = digit; if(0x02 == (0x02 & d)) expe[4] = digit; e = asc_buf[++now]; d = hextodec(e); if(0x08 == (0x08 & d)) tipex = digit; if(0x04 == (0x04 & d)) anex[0] = digit; if(0x02 == (0x02 & d)) anex[1] = digit; if(0x01 == (0x01 & d)) anex[2] = digit; k += long_lin; } return(0); }; puntua(beg) { int i, j, l, m, n, cc, k, r, offset; char a, b, c; unsigned char d, e, f; double p; k = -30; offset = 5; puntos = 0.00; bien = 0; mal = 0; blanco = 0; n = tipex - '0'; for(m = numpreg ; m > 0 ; m -= 30) { j = min(m,30); k += 30; /* Se suma al indice i para encontrar */ /* el numero de pregunta en cada momento */ r = 11*long_lin; for(i=1;i<=j;i++) { l = r + offset; a = asc_buf[beg + l]; e = hextodec(a); b = asc_buf[beg + l + 1]; if (b <= '8') d = b - '0'; else d = (b - 55) & 0x08; f = (e << 4) + d; cc = k + i; p = (double) punt[n][cc]; if (f == resp[n][cc]) { acierto[cc] = '1'; bien++; puntos += p; } else if(f==0) { blanco++; acierto[cc] = 'X'; } else { acierto[cc] = '0'; mal++; puntos -= penal*p; } r += long_lin; } offset +=2; } return(0); }; lee_sol(beg) { int i, j, k, l, m, n, r, offset; unsigned char d, e, f; char a, b, c; m = numpreg; offset = 5; k = - 30; n = tipex - '0'; for(m = numpreg ; m > 0 ; m -= 30 ) { j = min(m,30); k += 30; /* Se suma al indice i para encontrar */ /* el numero de pregunta en cada momento */ r = 11*long_lin; /* Longitud de la parte de identificacion */ for(i=1;i<=j;i++) { l = r + offset; a = asc_buf[beg + l]; e = hextodec(a); b = asc_buf[beg + l + 1]; if (b <= '8') d = b - '0'; else d = (b - 55) & 0x08; f = (e << 4) + d; resp[n][k+i] = f; r += long_lin; } offset +=2; } return(0); }; lee_punt(beg) { int i, j, k, l, m, n, r, offset; unsigned char d, e, f; char a,b,c; offset = 5; k = - 30; n = tipex - '0'; for(m = numpreg ; m > 0 ; m -= 30) { j = min(m,30); k += 30; /* Se suma al indice i para encontrar */ /* el numero de pregunta en cada momento */ r = 11*long_lin; /* Longitud de la parte de identificacion */ for(i=1;i<=j;i++) { l = r + offset; a = asc_buf[beg + l]; e = hextodec(a); b = asc_buf[beg + l + 1]; if (b <= '8') d = b - '0'; else d = (b - 55) & 0x08; f = (e << 4) + d; f = (f >> 3); punt[n][k+i] = f; r += long_lin; } offset +=2; } return(0); }; cabecera() { cls(); crt_mode(2); fputs("CORRIGE -- Programa para correccion automatica de examenes\n", stdout); fputs(" Ultima revision: 19/6/1989, (C) F. Tusell\n", stdout); return(0); }; main(argc,argv){ /* Inicializaciones y primera pantalla */ int i, j, numord = 0; cabecera(); crt_srcp(5,2,0); fputs("Introduzca numero de examenes diferentes : ",stdout); scanf("%d",&numexam); crt_srcp(6,2,0); fputs("Introduzca numero (comun) de preguntas : ",stdout); scanf("%d",&numpreg); acierto[numpreg+1] = "\0"; crt_srcp(7,2,0); fputs("Introduzca fraccion de penalizacion : ",stdout); scanf("%lf",&penal); asc_enb(); for(j=0; j<=numexam-1; j++) { crt_srcp(9,2,0); printf("Introduzca soluciones examen %d ---> ",j); while(1) { if(asc_in[0] != asc_out[0]) { i = asc_out[0]; if (asc_buf[i] == '$') { beg = i - long_ex; identifi(beg); lee_sol(beg); pliega; break; } else asc_out[0]++; } } crt_srcp(9,2,0); printf("Introduzca hoja de puntos examen %d ---> ",j); while(1) { if(asc_in[0] != asc_out[0]) { i = asc_out[0]; if (asc_buf[i] == '$') { beg = i - long_ex; lee_punt(beg); pliega; break; } else asc_out[0]++; } } } /* Busca un examen. Se examinan caracteres del buffer hasta encontrar un '$' (fin de registro). Si es asi, se procesa. */ cls(); crt_mode(2); fputs("CORRIGE -- Programa para correccion automatica de examenes\n", stdout); fputs(" Ultima revision: 19/6/1989, (C) F. Tusell\n", stdout); crt_srcp(5,12,0); fputs("------------------ S T A T U S ------------------\n\n\n",stdout); ptr = fopen("notas.dat","w"); for( ; ; ) { while(asc_in[0] != asc_out[0]) { i = asc_out[0]; if (asc_buf[i] == '$') { beg = i - long_ex; identifi(beg); puntua(beg); crt_srcp(8,0,0); numord++; printf("D.N.I. = %s\nExped. = %s\nTipo = %1c\nAnexos = %s\n", dni,expe,tipex,anex); printf("Puntos = %6.2f",puntos); crt_srcp(8,35,0); printf("Numero de orden = %d",numord); crt_srcp(9,35,0); printf("Primer apellido = %s",anex); crt_srcp(10,35,0); printf("Segundo apellido = %s",anex); crt_srcp(11,35,0); printf("Nombre = %s",anex); crt_srcp(12,35,0); printf("Bien/Blanco/Mal = %3d, %3d, %3d",bien,blanco,mal); fprintf(ptr,"%5s %8s %4d%3d%3d%3d%8.2f %s %s\n", expe,dni,numord,bien,blanco,mal,puntos,anex,&acierto[1]); pliega; } else { asc_out[0]++; } } /* Comprueba si un caracter esta esperando en el buffer del teclado */ if (wait_char()) { if ((pide_inst() == 0x0041) | (pide_inst() == 0x0061)) termina(); /* La orden era 'A' o 'a' */ } } }