]> git.llucax.com Git - z.facultad/75.08/llamadas.git/blobdiff - doc/Informe7508.lyx
Agrego afimonio_daemon.sh y creo que con eso está finiquitado el informe.
[z.facultad/75.08/llamadas.git] / doc / Informe7508.lyx
index d57ec827148c110fa27ce61ab5e551555c203693..08b52c020129b2c927f76d2584a79d574d3195bd 100644 (file)
@@ -52,7 +52,7 @@ Leandro Lucarella (77891)
 Ricardo Markiewicz (78226)
 \layout Date
 
 Ricardo Markiewicz (78226)
 \layout Date
 
-Primera Entrega, 28 de Junio del 2004
+26 de Octubre del 2004
 \layout Standard
 
 
 \layout Standard
 
 
@@ -63,9 +63,6 @@ Primera Entrega, 28 de Junio del 2004
 
 \layout Chapter
 
 
 \layout Chapter
 
-Desarollo e Implementación
-\layout Section
-
 Hipotesis y Aclaraciones
 \layout Itemize
 
 Hipotesis y Aclaraciones
 \layout Itemize
 
@@ -73,7 +70,7 @@ El programa en su totalidad va a ser ejecutado por un 
  configuración diferente es posible pero queda en manos del administrador.
 \layout Itemize
 
  configuración diferente es posible pero queda en manos del administrador.
 \layout Itemize
 
-En los archivos de llamada se valida que sean numeros, y para validar la
+En los archivos de llamada se valida que sean números, y para validar la
  fecha no se tiene en cuenta casos particulares como el 29, 30, 31 de febrero.
 \layout Itemize
 
  fecha no se tiene en cuenta casos particulares como el 29, 30, 31 de febrero.
 \layout Itemize
 
@@ -84,7 +81,26 @@ Aficonf utiliza n
  La opción Borrar es ofrecida requiriendo un número de ID a borrar dependiendo
  de los resultados de la búsqueda, y dando una opción (-1) para cancelar
  la acción.
  La opción Borrar es ofrecida requiriendo un número de ID a borrar dependiendo
  de los resultados de la búsqueda, y dando una opción (-1) para cancelar
  la acción.
-\layout Section
+\layout Itemize
+
+El instalador utiliza el archivo 
+\family typewriter 
+afinstal.conf
+\family default 
+, situado en el directorio 
+\family typewriter 
+$PATH_INSTALADOR/conf
+\family default 
+, para determinar que componentes se encuentran instalados.
+ Internamente, en base a la información de paths proporcionada por este
+ archivo, busca su los binarios realmente se encuentran en el OS, y en caso
+ contrario permite volver a reinstalarlo/s.
+\layout Chapter
+
+
+\begin_inset LatexCommand \label{sec:Problemas-relevantes}
+
+\end_inset 
 
 Problemas relevantes
 \layout Itemize
 
 Problemas relevantes
 \layout Itemize
@@ -108,29 +124,114 @@ As
 \family typewriter 
 /etc/antifraude
 \family default 
 \family typewriter 
 /etc/antifraude
 \family default 
-, pero como no podríamos suponer root access preferimos directamente trabajar
- en el home del usuario.
-\layout Section
+, pero como no podríamos suponer acceso de 
+\emph on 
+root
+\emph default 
+ preferimos directamente trabajar en el directorio del usuario.
+\layout Chapter
 
 Instalación
 \layout Standard
 
 
 Instalación
 \layout Standard
 
-Copiar del README cuando este terminado y extenderlo un poco si se considera
- necesario.
-\layout Section
-
-Comandos Desarrollados
-\layout Subsection
+Una vez descargados los fuentes (asumiremos que ha descargado el 
+\family typewriter 
+tar.gz
+\family default 
+) solo debe descomprimir el archivo ejecutando el siguiente comando:
+\layout LyX-Code
 
 
-AFIMONIO
+tar xvzf grupo12.tar.gz
 \layout Standard
 
 \layout Standard
 
+Esto creará la siguiente estructura de directorios:
+\layout LyX-Code
+
+./
+\layout LyX-Code
+
+ +- grupo12
+\layout LyX-Code
+
+ |
+\layout LyX-Code
+
+ +-- README
+\layout LyX-Code
+
+ +-- COPYING
+\layout LyX-Code
+
+ +-- afinstal
+\layout LyX-Code
+
+ +-- conf
+\layout LyX-Code
+
+ +---- umbrales.param
+\layout LyX-Code
+
+ +---- umbrales.id
+\layout LyX-Code
+
+ +---- oridesti.txt
+\layout LyX-Code
+
+ +-- inst
+\layout LyX-Code
+
+ +---- afimonio
+\layout LyX-Code
+
+ +---- antifraude.pl
+\layout LyX-Code
+
+ +---- aficonf
+\layout LyX-Code
+
+ +---- afimonio_daemon.sh
+\layout LyX-Code
+
+ +---- util.sh
+\layout LyX-Code
+
+ +---- callgen
+\layout LyX-Code
+
+ +---- testcalls.tar.gz
+\layout Standard
 
 
+Para proceder a la instalación del sistema 
 \series bold 
 \series bold 
-Tipo de comando:
+antifraude
 \series default 
 \series default 
- Solicitado
-\layout Subsubsection
+ debe correr el script 
+\series bold 
+afinstal
+\series default 
+:
+\layout LyX-Code
+
+./afinstal
+\layout Standard
+
+y seguir los pasos que se le indiquen a continuación.
+ De no ejecutar apropiadamente la instalación, no se garantiza el correcto
+ funcionamiento de los componentes.
+\layout Chapter
+
+Comandos Desarrollados
+\layout Section
+
+AFIMONIO
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
 
 Archivos de Input
 \layout Standard
 
 Archivos de Input
 \layout Standard
 \family default 
 \series medium 
  según corresponda.
 \family default 
 \series medium 
  según corresponda.
-\layout Subsubsection
+\layout Subsection
 
 Archivos de Output
 \layout Standard
 
 
 Archivos de Output
 \layout Standard
 
-El afimonio genera una salida al archivo afimonio.log la cual contiene informació
-n sobre la ejecución del programa.
+El afimonio genera una salida al archivo 
+\family typewriter 
+afimonio.log
+\family default 
+ la cual contiene información sobre la ejecución del programa.
 \layout Standard
 
 Si un archivo es válido, se añade una línea con el siguiente formato: 
 \layout Standard
 
 Si un archivo es válido, se añade una línea con el siguiente formato: 
-\layout Standard
+\layout LyX-Code
 
 
-"$fecha $USER afimonio: "Se detecta archivo de llamadas $file" 
+$fecha $USER afimonio: "Se detecta archivo de llamadas $file"
 \layout Standard
 
 Si el archivo tuviera un nombre inválido, la línea seria la siguiente: 
 \layout Standard
 
 Si el archivo tuviera un nombre inválido, la línea seria la siguiente: 
-\layout Standard
+\layout LyX-Code
 
 
-"$fecha $USER afimonio:"Se rechaza el archivo $file".
+$fecha $USER afimonio: "Se rechaza el archivo $file"
 \layout Standard
 
 \layout Standard
 
-donde 
-\layout Standard
+donde:
+\layout Description
 
 
-$fecha: fecha actual con formato Día-Mes-Año-Hora:Minuto.
-\layout Standard
 
 
-$USER: nombre de usuario que ejecuto el script.
+\family typewriter 
+$fecha
+\family default 
+ fecha actual con formato Día-Mes-Año-Hora:Minuto.
+\layout Description
+
+
+\family typewriter 
+$USER
+\family default 
+ nombre de usuario que ejecuto el script.
+\layout Description
+
+
+\family typewriter 
+$file
+\family default 
+ nombre del archivo que se procesó.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio
 \layout Standard
 
 \layout Standard
 
-$file: nombre del archivo que se procesó.
+Corre el programa en primer plano.
 \layout Subsubsection
 
 \layout Subsubsection
 
-Ejemplos de invocación
+
+\family typewriter 
+nohup ./afimonio &
+\layout Standard
+
+Corre el programa en segundo plano, evitando que se cierre al morir el padre
+ desasociándolo de la terminal.
+ La salida del programa queda en el archivo 
+\family typewriter 
+nohup.out
+\family default 
+ a menos que se redirija a otro archivo.
+\layout Subsection
+
+Código Fuente
 \layout LyX-Code
 
 \layout LyX-Code
 
-:afimonio/bin$> ./afimonio
+#!/bin/bash
 \layout LyX-Code
 
 \layout LyX-Code
 
-:afimonio/bin$> nohup ./afimonio & 
 \layout LyX-Code
 
 \layout LyX-Code
 
-:afimonio/bin$> ./afimonio_daemon.sh
+BASE_DIR=$HOME/.antifraude
 \layout LyX-Code
 
 \layout LyX-Code
 
-    afimonio_daemon.sh (start|stop|status)
-\layout Subsubsection
+\layout LyX-Code
 
 
-Código Fuente
-\layout Standard
+# uso las funciones de util.sh
+\layout LyX-Code
 
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+.
+ "$HOME/.antifraude/util.sh"
+\layout LyX-Code
 
 
-ANTIFRAUDE
-\layout Standard
+.
+ "$HOME/.antifraude/conf/afimonio.conf"
+\layout LyX-Code
 
 
+.
+ "$HOME/.antifraude/conf/antifraude.conf"
+\layout LyX-Code
 
 
-\series bold 
-Tipo de comando:
-\series default 
- Solicitado
-\layout Subsubsection
+\layout LyX-Code
 
 
-Archivos de Input
-\layout Standard
+# Es llamada por los trap para deslockear el afimonio 
+\layout LyX-Code
 
 
-Procesa los archivos de llamadas que encuentre en el momento de invocación
- en el directorio 
-\family typewriter 
-$PATH_ANTIFRAUDE/$DATADIR/enproceso
-\family default 
-.
- El demonio 
-\series bold 
-Afimonio
-\series default 
- será quien alimentará al 
-\series bold 
-Antifraude
-\series default 
- con dichos archivos, no obstante se lo puede alimentar con archivos de
- llamadas en forma manual, situándolos en el directorio anteriormente descripto.
-\layout Subsubsection
+finalize() {
+\layout LyX-Code
 
 
-Archivos de Output
-\layout Itemize
+        unlock "afimonio" 
+\layout LyX-Code
 
 
+        exit 0
+\layout LyX-Code
 
 
-\series bold 
-Antifraude.log:
-\series default 
- Se loguea en este archivo el procesamiento de los registros, warnings provocado
-s por registros no validos y alarmas emitidas por registros que matchean
- contra un umbral.
-\layout Itemize
+}
+\layout LyX-Code
 
 
+# filtra el nombre del archivo pasado por parametro sacandole
+\layout LyX-Code
 
 
-\series bold 
-Alarmas.txt:
-\series default 
- Se loguean en este archivo las alarmas provocadas por registros en los
- archivos de llamadas, que hayan matcheado un umbral determinado del archivo
- umbrales.param.
-\layout Subsubsection
+# todos los caracteres que no sean numeros 
+\layout LyX-Code
 
 
-Ejemplos de invocación
+checkfilename(){
 \layout LyX-Code
 
 \layout LyX-Code
 
-:antifraude/bin$> perl antifraude.pl
+        date=`echo $1 | cut -d "." -f 1`
 \layout LyX-Code
 
 \layout LyX-Code
 
-:antifraude/bin$> perl antifraude.pl &
-\layout Subsubsection
+        central=`echo $1 | cut -d "." -f 2`
+\layout LyX-Code
 
 
-Código Fuente
-\layout Standard
+        validar_solo_numeros "$date"
+\layout LyX-Code
 
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
 
-AFICONF
-\layout Standard
+                return 1
+\layout LyX-Code
 
 
+        fi
+\layout LyX-Code
 
 
-\series bold 
-Tipo de comando:
-\series default 
- Solicitado
-\layout Subsubsection
+        mes=${date:4:2}
+\layout LyX-Code
 
 
-Archivos de Input
-\layout Standard
+        validar_rango "$mes" "1" "12"
+\layout LyX-Code
 
 
-El comando utiliza los archivos umbrales.param y oridesti.txt situados en
-\family typewriter 
-~$HOME/.antifraude/
-\layout Subsubsection
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
 
-Archivos de Output
-\layout Standard
+                return 1
+\layout LyX-Code
 
 
-Solo escribe en umbrales.param de ser solicitado por el usuario, ya sea por
- la alta o baja de un umbral.
-\layout Subsubsection
+        fi
+\layout LyX-Code
 
 
-Ejemplos de invocación
+        dia=${date:6:2}
 \layout LyX-Code
 
 \layout LyX-Code
 
-:aficonf/bin$> ./aficonf
-\layout Subsubsection
+        validar_rango "$dia" "1" "31" 
+\layout LyX-Code
+
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        hora=${date:8:2}
+\layout LyX-Code
+
+        validar_rango "$hora" "0" "23"
+\layout LyX-Code
+
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        min=${date:10:2}
+\layout LyX-Code
+
+        validar_rango "$min" "0" "59"
+\layout LyX-Code
+
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        validar_solo_numeros "$central"
+\layout LyX-Code
+
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        return 0                
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#--------------------MAIN SCRIPT----------------------
+\layout LyX-Code
+
+# Recupero las rutas a todos los directorios y archivos
+\layout LyX-Code
+
+# que necesito del antifraude
+\layout LyX-Code
+
+DATADIR=$ANTI_DATADIR
+\layout LyX-Code
+
+SOURCEDIR=$DATADIR/aprocesar/
+\layout LyX-Code
+
+ACEPTDIR=$DATADIR/enproceso/
+\layout LyX-Code
+
+REJECTDIR=$DATADIR/rechazadas/
+\layout LyX-Code
+
+BINDIR=$ANTI_BINDIR
+\layout LyX-Code
+
+# Del afimonio
+\layout LyX-Code
+
+LOGDIR=$AFIM_LOGDIR
+\layout LyX-Code
+
+LOGNAME=$AFIM_LOGFILE
+\layout LyX-Code
+
+LOGFILE=$LOGDIR/$LOGNAME
+\layout LyX-Code
+
+# Capturo señales para salir bien (liberando el lock)
+\layout LyX-Code
+
+trap "finalize" INT
+\layout LyX-Code
+
+trap "finalize" TERM 
+\layout LyX-Code
+
+# Me lockeo
+\layout LyX-Code
+
+lock "afimonio" || die "No se puede correr, hay otra 
+\backslash 
+
+\layout LyX-Code
+
+instancia corriendo o no se puede crear el lock file!"
+\layout LyX-Code
+
+# Comienza el ciclo infinito que mueve los archivos
+\layout LyX-Code
+
+while true; do 
+\layout LyX-Code
+
+        files=
+\layout LyX-Code
+
+        for file in `ls $SOURCEDIR` ; do
+\layout LyX-Code
+
+                files=1
+\layout LyX-Code
+
+                checkfilename $file     
+\layout LyX-Code
+
+                if [ "$?" -eq 0 ]; then
+\layout LyX-Code
+
+                        mv "$SOURCEDIR$file" "$ACEPTDIR"
+\layout LyX-Code
+
+                        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+                        echo "$fecha $USER afimonio:
+\backslash 
+"Se detecta " 
+\backslash 
+
+\layout LyX-Code
+
+                          "archivo de llamadas $file
+\backslash 
+"" >> $LOGFILE
+\layout LyX-Code
+
+                else 
+\layout LyX-Code
+
+                        mv "$SOURCEDIR$file" "$REJECTDIR"
+\layout LyX-Code
+
+                        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+                        echo "$fecha $USER afimonio:
+\backslash 
+"Se rechaza " 
+\backslash 
+
+\layout LyX-Code
+
+                          "el archivo $file
+\backslash 
+"" >> $LOGFILE
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                clean_log "$LOGFILE" "$AFIM_LOGSIZE"
+\layout LyX-Code
+
+        done #for
+\layout LyX-Code
+
+        # me fijo si el antifraude esta corriendo y si no lo esta
+\layout LyX-Code
+
+        # lo arranco
+\layout LyX-Code
+
+        if [ -n $files ] && ! is_lock "antifraude.pl"; then
+\layout LyX-Code
+
+                $BINDIR/antifraude.pl &
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        sleep 5
+\layout LyX-Code
+
+done #while
+\layout Section
+
+ANTIFRAUDE.PL
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Procesa los archivos de llamadas que encuentre en el momento de invocación
+ en el directorio 
+\family typewriter 
+$PATH_ANTIFRAUDE/$DATADIR/enproceso
+\family default 
+.
+ El demonio 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ será quien alimentará al 
+\family typewriter 
+\series bold 
+antifraude
+\family default 
+\series default 
+ con dichos archivos, no obstante se lo puede alimentar con archivos de
+ llamadas en forma manual, situándolos en el directorio anteriormente descripto.
+\layout Standard
+
+Este comando, en el momento de invocacion genera y guarda internamente un
+ listado de los archivos de llamadas presences en el directorio 
+\family typewriter 
+/enproceso
+\family default 
+, ordenándolos por fecha (establecida en el nombre del archivo) en forma
+ ascendente.
+ Dado que utiliza durante toda su ejecución esta lista interna, el 
+\family typewriter 
+\series bold 
+Afimonio
+\family default 
+\series default 
+ puede alimentar al directorio 
+\family typewriter 
+/enproceso
+\family default 
+ con nuevos archivos mientras el 
+\family typewriter 
+\series bold 
+Antifraude
+\family default 
+\series default 
+ corre, pero los mismos no serán tenidos en cuenta (esto es, procesados),
+ hasta la próxima invocación del comando.
+\layout Subsection
+
+Archivos de Output
+\layout Description
+
+
+\family typewriter 
+Antifraude.log
+\family default 
+ En este archivo se guarda información del procesamiento de los registros,
+ advertencias provocados por registros no validos y alarmas emitidas por
+ registros que cumplen con un umbral.
+\layout Description
+
+
+\family typewriter 
+Alarmas.txt
+\family default 
+ En este archivo se guarda información de las alarmas provocadas por registros
+ en los archivos de llamadas, que hayan cumplido un umbral determinado del
+ archivo 
+\family typewriter 
+umbrales.param
+\family default 
+.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./antifraude.pl
+\layout Standard
+
+El programa procesa las llamadas 
+\family typewriter 
+enproceso
+\family default 
+ como indica el enunciado en primer plano.
+\layout Subsubsection
+
+
+\family typewriter 
+perl antifraude.pl
+\layout Standard
+
+Ídem anterior.
+\layout Subsubsection
+
+
+\family typewriter 
+./antifraude.pl &
+\layout Standard
+
+Ídem anterior pero procesa en segundo plano.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/usr/bin/perl
+\layout LyX-Code
+
+sub is_lock {
+\layout LyX-Code
+
+        if ( -e "$ENV{'HOME'}/.antifraude/lock/antifraude.pid" ) {
+\layout LyX-Code
+
+                # Lock file encontrado
+\layout LyX-Code
+
+                return 1;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        # No hay lock file!
+\layout LyX-Code
+
+        return 0;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub unlock {
+\layout LyX-Code
+
+        unlink ("$ENV{'HOME'}/.antifraude/lock/antifraude.pid");
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub lock {
+\layout LyX-Code
+
+        if (!is_lock()) {
+\layout LyX-Code
+
+                local $lfile = "$ENV{'HOME'}/.antifraude/lock/antifraude.pid";
+\layout LyX-Code
+
+                open(LOCKFILE,">>$lfile");
+\layout LyX-Code
+
+                print LOCKFILE $$;
+\layout LyX-Code
+
+                close(LOCKFILE);
+\layout LyX-Code
+
+                return 1;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        return 0;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Comparador de fecha para los archivos de llamada
+\layout LyX-Code
+
+sub byDate {
+\layout LyX-Code
+
+        ($year1,$mon1,$day1,$hr1,$min1) =
+\layout LyX-Code
+
+          $a =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
+\layout LyX-Code
+
+        ($year2,$mon2,$day2,$hr2,$min2) =
+\layout LyX-Code
+
+          $b =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        # Descarto por año
+\layout LyX-Code
+
+        if ($year1 > $year2) { return 1; }
+\layout LyX-Code
+
+        elsif ($year1 < $year2) { return -1; }
+\layout LyX-Code
+
+        # Descarto por mes
+\layout LyX-Code
+
+        if ($mon1 > $mon2) { return 1; }
+\layout LyX-Code
+
+        elsif ($mon1 < $mon2) { return -1; }
+\layout LyX-Code
+
+        # Calculo minutos de lo restante
+\layout LyX-Code
+
+        $totalmin1 = ($day1 * 24 * 60) + ($hr1 * 60) + $min1;
+\layout LyX-Code
+
+        $totalmin2 = ($day2 * 24 * 60) + ($hr2 * 60) + $min2;
+\layout LyX-Code
+
+        if ($totalmin1 > $totalmin2) { return 1; }
+\layout LyX-Code
+
+        elsif ($totalmin1 < $totalmin2) { return -1; }
+\layout LyX-Code
+
+        else { return 0; }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Devuelve un listado de archivos de llamada y ordenado por fecha ASC
+\layout LyX-Code
+
+sub getCallFiles {
+\layout LyX-Code
+
+        # Obtengo listado de archivos de llamadas y lo ordeno por fecha
+\layout LyX-Code
+
+        opendir($DIR,"$CONFDATA{datadir}/enproceso")
+\layout LyX-Code
+
+          or die 'Could not open dir';
+\layout LyX-Code
+
+        # Valido solo fisicamente, lo logico ya valido afimonio..
+\layout LyX-Code
+
+        @files = grep {/[0-9]{12}
+\backslash 
+.[0-9]{4}$/
+\layout LyX-Code
+
+          && -f "$CONFDATA{datadir}/enproceso/$_"} readdir($DIR);
+\layout LyX-Code
+
+        @sortedfiles = sort byDate @files;
+\layout LyX-Code
+
+        closedir($DIR);
+\layout LyX-Code
+
+        return @sortedfiles;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Levanta una variable del archivo AFINSTAL.CONF
+\layout LyX-Code
+
+sub getConfVar {
+\layout LyX-Code
+
+        $CONFIGFILE = shift(@_);
+\layout LyX-Code
+
+        my $linenumber = shift(@_);
+\layout LyX-Code
+
+        open(CONFIGFILE)
+\layout LyX-Code
+
+          or die "No se pudo abrir el archivo $CONFIGFILE";
+\layout LyX-Code
+
+        do { $line = <CONFIGFILE> } until $.
+ == $linenumber;
+\layout LyX-Code
+
+        close(CONFIGFILE);
+\layout LyX-Code
+
+        chop($line);
+\layout LyX-Code
+
+        ($confvar = $line) =~ s/"(.*)"$/$1/;
+\layout LyX-Code
+
+        $confvar =~ s/^.*=//;
+\layout LyX-Code
+
+        return $confvar;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Agrega un log entry al logfile del antifraude.pl
+\layout LyX-Code
+
+sub logEntry {
+\layout LyX-Code
+
+        my $logentry = shift(@_);
+\layout LyX-Code
+
+        my $consoleout = shift(@_);
+\layout LyX-Code
+
+        my $log = "$CONFDATA{logdir}/$CONFDATA{logfile}";
+\layout LyX-Code
+
+        # Fetch date and Format it
+\layout LyX-Code
+
+        ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
+\layout LyX-Code
+
+          = localtime(time);
+\layout LyX-Code
+
+        $mon =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $mday =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $hour =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $min =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $year += 1900; ++$mon;
+\layout LyX-Code
+
+        $user = "$ENV{USER}";
+\layout LyX-Code
+
+        $commonstring = "$mday/$mon/$year-$hour:$min $user antifraude:";
+\layout LyX-Code
+
+        # Append to log
+\layout LyX-Code
+
+        open(LOGFILE,">>$log")
+\layout LyX-Code
+
+          or die "No se pudo abrir el archivo de log";
+\layout LyX-Code
+
+        seek(LOGFILE,0,2);
+\layout LyX-Code
+
+        print LOGFILE "$commonstring 
+\backslash 
+"$logentry
+\backslash 
+"
+\backslash 
+n";
+\layout LyX-Code
+
+        $filesize = tell(LOGFILE);
+\layout LyX-Code
+
+        close(LOGFILE);
+\layout LyX-Code
+
+        # Chequeo el logsize y su lo supero me quedo con 100 lineas
+\layout LyX-Code
+
+        if ($filesize > $CONFDATA{logsize})
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                open(LOGFILE,"+<$log");
+\layout LyX-Code
+
+                do ($line = <LOGFILE>) until $.
+ == 100;
+\layout LyX-Code
+
+                truncate(LOGFILE,tell(LOGFILE));
+\layout LyX-Code
+
+                close(LOGFILE);
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        if ($consoleout) { print("$logentry
+\backslash 
+n"); }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub badCall {
+\layout LyX-Code
+
+        my $callreg = shift(@_);
+\layout LyX-Code
+
+        my $numreg = shift(@_);
+\layout LyX-Code
+
+        logEntry("El siguiente registro de llamada tiene format ".
+\layout LyX-Code
+
+          "o invalido
+\backslash 
+n$callreg",0);
+\layout LyX-Code
+
+        print("Warning: El registro de llamada $numreg tiene ".
+\layout LyX-Code
+
+          "formato invalido
+\backslash 
+n");
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub checkUmbrales {
+\layout LyX-Code
+
+        local(*callfields) = $_[0];
+\layout LyX-Code
+
+        my $callsfile = $_[1];
+\layout LyX-Code
+
+        my $matchedUmbral = 0;
+\layout LyX-Code
+
+        my $i = 0;
+\layout LyX-Code
+
+        while (($i <= $#UMBRALES) && ($matchedUmbral == 0)) {
+\layout LyX-Code
+
+                $umbral = $UMBRALES[$i];
+\layout LyX-Code
+
+                chomp($umbral);
+\layout LyX-Code
+
+                ($regid,$phoneline,$oridest,$type,$state)
+\layout LyX-Code
+
+                  = split(';',$umbral);
+\layout LyX-Code
+
+                if (($state eq 'A') && ($callfields[0] == $phoneline)
+\layout LyX-Code
+
+                  && ($callfields[4] eq $type)) {
+\layout LyX-Code
+
+                        # Si es Saliente y coincide el Destino con el
+\layout LyX-Code
+
+                        # Ori/Dest del umbral
+\layout LyX-Code
+
+                        if (($type eq 'S')
+\layout LyX-Code
+
+                          && ($callfields[5] eq $oridest)) {
+\layout LyX-Code
+
+                                $matchedUmbral = $regid;
+\layout LyX-Code
+
+                        }
+\layout LyX-Code
+
+                        if (($type eq 'E')
+\layout LyX-Code
+
+                          && ($callfields[6] eq $oridest)) {
+\layout LyX-Code
+
+                                $matchedUmbral = $regid;
+\layout LyX-Code
+
+                        }
+\layout LyX-Code
+
+                }                       
+\layout LyX-Code
+
+                ++$i;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        # Si se matcheo un umbral, grabo una alarma y aviso por consola
+\layout LyX-Code
+
+        if ($matchedUmbral > 0) {
+\layout LyX-Code
+
+                # Obtengo algunos datos
+\layout LyX-Code
+
+                ($central = $callsfile) =~ s/^.*
+\backslash 
+.//;
+\layout LyX-Code
+
+                $user = "$ENV{USER}";
+\layout LyX-Code
+
+                # Fetch date and Format it
+\layout LyX-Code
+
+                ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
+\layout LyX-Code
+
+                  = localtime(time);
+\layout LyX-Code
+
+                $year += 1900; ++$mon;
+\layout LyX-Code
+
+                $mon =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $mday =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $hour =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $min =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $sec =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $user = "$ENV{USER}";
+\layout LyX-Code
+
+                $date = "${year}${mon}${mday}";
+\layout LyX-Code
+
+                $time = "${hour}${min}${sec}";
+\layout LyX-Code
+
+                # Preparo el registro de alarma
+\layout LyX-Code
+
+                $alarmEntry = "$callfields[7];$central;$callfields[0];".
+\layout LyX-Code
+
+                  "$callfields[1];$regid;$callfields[2];".
+\layout LyX-Code
+
+                  "$callfields[3];$user;$date;$time";
+\layout LyX-Code
+
+                # Grabamos el registro en el archivo de alarmas
+\layout LyX-Code
+
+                $alarmlog = "$CONFDATA{datadir}/alarmas/alarmas.txt";
+\layout LyX-Code
+
+                open(ALARMFILE,">>$alarmlog")
+\layout LyX-Code
+
+                  or die 'No se pudo abrir el archivo de alarmas';
+\layout LyX-Code
+
+                seek(ALARMFILE,0,2);
+\layout LyX-Code
+
+                print ALARMFILE "$alarmEntry
+\backslash 
+n";
+\layout LyX-Code
+
+                close(ALARMFILE);
+\layout LyX-Code
+
+                # Logeo por consola y logfile que hubo una alarma
+\layout LyX-Code
+
+                logEntry("Alarma: Se ha matcheado el registro procesado"
+\layout LyX-Code
+
+                  ." con el umbral nro $matchedUmbral",1);
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# --------- MAIN CODE -------- #
+\layout LyX-Code
+
+# File locking..
+\layout LyX-Code
+
+if (is_lock()) { exit 1; }
+\layout LyX-Code
+
+lock();
+\layout LyX-Code
+
+# Defino some GLOBALS
+\layout LyX-Code
+
+$CONFDIR = "$ENV{'HOME'}/.antifraude";
+\layout LyX-Code
+
+$CONFDATA{logdir} = getConfVar("$CONFDIR/conf/antifraude.conf",2);
+\layout LyX-Code
+
+$CONFDATA{logfile} = getConfVar("$CONFDIR/conf/antifraude.conf",3);
+\layout LyX-Code
+
+$CONFDATA{logsize} = getConfVar("$CONFDIR/conf/antifraude.conf",4);
+\layout LyX-Code
+
+$CONFDATA{datadir} = getConfVar("$CONFDIR/conf/antifraude.conf",5);
+\layout LyX-Code
+
+# Cargo los UMBRALES en memoria
+\layout LyX-Code
+
+open(PARAMFILE,"$CONFDIR/umbrales.param") or die "No se pudo abrir el "
+\layout LyX-Code
+
+  ."archivo de umbrales";
+\layout LyX-Code
+
+@UMBRALES = <PARAMFILE>;
+\layout LyX-Code
+
+close(PARAMFILE);
+\layout LyX-Code
+
+# Proceso los archivos de llamadas
+\layout LyX-Code
+
+@archivos = getCallFiles();
+\layout LyX-Code
+
+FILE: foreach $filename (@archivos) {
+\layout LyX-Code
+
+        $regnum = 0;
+\layout LyX-Code
+
+        $CALLFILE = "$CONFDATA{datadir}/enproceso/$filename";
+\layout LyX-Code
+
+        logEntry("Inicio proceso de: $filename",1);
+\layout LyX-Code
+
+        open(CALLFILE)
+\layout LyX-Code
+
+          or ((warn "No se pudo abrir archivo $filename"),next FILE);
+\layout LyX-Code
+
+        REG: foreach $callreg (<CALLFILE>) {
+\layout LyX-Code
+
+                logEntry("Procesando Reg: $regnum | Archivo: $filename",1);
+\layout LyX-Code
+
+                chomp($callreg);
+\layout LyX-Code
+
+                $fieldcount = split(';',$callreg);
+\layout LyX-Code
+
+                @fields = @_;
+\layout LyX-Code
+
+                # Si no tengo 8 campos exactamente, invalido
+\layout LyX-Code
+
+                if ($fieldcount != 8)
+\layout LyX-Code
+
+                {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum);
+\layout LyX-Code
+
+                        next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Si la linea no es un numero, invalido
+\layout LyX-Code
+
+                $fields[0] =~ s/^
+\backslash 
+s*(
+\backslash 
+w*)
+\backslash 
+s*$/$1/;
+\layout LyX-Code
+
+                if (!($fields[0] =~ /^
+\backslash 
+d+$/))
+\layout LyX-Code
+
+                {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum);
+\layout LyX-Code
+
+                        next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Si tipo llamada ! E|S o no se informa Origen
+\layout LyX-Code
+
+                # o Destino, invalido
+\layout LyX-Code
+
+                if (($fields[4] ne 'E') && ($fields[4] ne 'S')) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                if (($fields[4] eq 'E') && ($fields[6] eq "")) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                if (($fields[4] eq 'S') && ($fields[5] eq "")) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Ya pase todas las validaciones, ahora busco si
+\layout LyX-Code
+
+                # exite un umbral
+\layout LyX-Code
+
+                checkUmbrales(*fields,$filename);
+\layout LyX-Code
+
+        } continue { ++$regnum }
+\layout LyX-Code
+
+        close(CALLFILE);
+\layout LyX-Code
+
+        # La muevo al directorio de procesadas
+\layout LyX-Code
+
+        rename $CALLFILE,"$CONFDATA{datadir}/procesadas/$filename";
+\layout LyX-Code
+
+        logEntry("Fin proceso de: $filename",1);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Unlocking
+\layout LyX-Code
+
+unlock();
+\layout Section
+
+AFICONF
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+El comando utiliza los archivos 
+\family typewriter 
+umbrales.param
+\family default 
+ y 
+\family typewriter 
+oridesti.txt
+\family default 
+ situados en 
+\family typewriter 
+~$HOME/.antifraude/
+\layout Subsubsection
+
+Archivos de Output
+\layout Standard
+
+Solo escribe en 
+\family typewriter 
+umbrales.param
+\family default 
+ de ser solicitado por el usuario, ya sea por la alta o baja de un umbral.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./aficonf
+\layout Standard
+
+Realiza lo pedido en el enunciado.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/bin/sh
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Configurador
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo config
+\layout LyX-Code
+
+BASE_DIR="$HOME/.antifraude"
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo config
+\layout LyX-Code
+
+.
+ "$BASE_DIR/conf/aficonf.conf"
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo utilidades
+\layout LyX-Code
+
+.
+ "$BASE_DIR/util.sh"
+\layout LyX-Code
+
+LOGDIR=$AFIC_LOGDIR
+\layout LyX-Code
+
+LOGNAME=$AFIC_LOGFILE
+\layout LyX-Code
+
+LOGFILE=$LOGDIR/$LOGNAME
+\layout LyX-Code
+
+\layout LyX-Code
+
+#Valida que exista el pais
+\layout LyX-Code
+
+# Parámetros :
+\layout LyX-Code
+
+#   $1 = Descripcion a buscar
+\layout LyX-Code
+
+#   $2 = Variable donde guardar el código del Pais
+\layout LyX-Code
+
+#        en caso de existir
+\layout LyX-Code
+
+existe_pais () {
+\layout LyX-Code
+
+        EXISTE=`cat "$BASE_DIR/oridesti.txt" 
+\backslash 
+
+\layout LyX-Code
+
+          | egrep "^[A-Z]*;$1" | cut -d ';' -f 1`;
+\layout LyX-Code
+
+        if [ "$EXISTE" != "" ] ; then
+\layout LyX-Code
+
+                #Exite!, debo gaurdar el código
+\layout LyX-Code
+
+                eval "$2=$EXISTE"
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+poner_estado_umbral () {
+\layout LyX-Code
+
+        ID=$1
+\layout LyX-Code
+
+        ESTADO=$2
+\layout LyX-Code
+
+        FECHA=`date +"%Y%m%d"`
+\layout LyX-Code
+
+        HORA=`date +"%H%M%S"`
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        if [ "$ESTADO" != "A" ] && [ "$ESTADO" != "I" ]
+\layout LyX-Code
+
+        then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        SALIDA=`sed "s/^$ID
+\backslash 
+(;[^;]*;[^;]*;[^;]*;
+\backslash 
+)[^;]*
+\backslash 
+(;"
+\backslash 
+
+\layout LyX-Code
+
+"[^;]*;[^;]*;[^;]*
+\backslash 
+)$/$ID
+\backslash 
+1I;$USER;$FECHA;$HORA/" 
+\backslash 
+
+\layout LyX-Code
+
+          "$BASE_DIR/umbrales.param"`
+\layout LyX-Code
+
+        echo "$SALIDA" > "$BASE_DIR/umbrales.param"
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "Se ha cambiado el estado de umbral $ID a $ESTADO" 
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+menu () {
+\layout LyX-Code
+
+        echo "AFICONF"
+\layout LyX-Code
+
+        echo "======="
+\layout LyX-Code
+
+        echo
+\layout LyX-Code
+
+        echo "  1) Alta"
+\layout LyX-Code
+
+        echo "  2) Buscar"
+\layout LyX-Code
+
+        echo "  3) Salir"
+\layout LyX-Code
+
+        preguntar "Su opción" "123" $1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+existe_umbral () {
+\layout LyX-Code
+
+        EXISTE=`cat "$BASE_DIR/umbrales.param" | egrep "$1"`;
+\layout LyX-Code
+
+        if [ "$EXISTE" == "" ] ; then
+\layout LyX-Code
+
+                #No existe
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        #Ya existe un umbral!
+\layout LyX-Code
+
+        return 0
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+buscar_id_umbral () {
+\layout LyX-Code
+
+        ID=`cat "$BASE_DIR/umbrales.id"`;
+\layout LyX-Code
+
+        eval "$1=$ID"
+\layout LyX-Code
+
+        let ID=$ID+1
+\layout LyX-Code
+
+        echo "$ID" > "$BASE_DIR/umbrales.id"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+case_altas () {
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Número de línea" "" LINEA
+\layout LyX-Code
+
+                #TODO Valido
+\layout LyX-Code
+
+                if ! validar_solo_numeros "$LINEA" ; then
+\layout LyX-Code
+
+                        echo "EL NUMERO TE LINEA SOLO DEBE" 
+\backslash 
+
+\layout LyX-Code
+
+                        "TENER DIGITOS"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$LINEA" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        preguntar "Tipo de llamada" "ES" TIPO
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        CODIGO=''
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Pais (descripción)" "" PAIS 
+\layout LyX-Code
+
+                if ! existe_pais "$PAIS" CODIGO ; then
+\layout LyX-Code
+
+                        echo "No existe el país de descrición '$PAIS'"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$PAIS" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        echo "El código de '$PAIS' es '$CODIGO'"
+\layout LyX-Code
+
+        PAIS=$CODIGO
+\layout LyX-Code
+
+        # Verifico que el umbral no exista
+\layout LyX-Code
+
+        FECHA=`date +"%Y%m%d"`
+\layout LyX-Code
+
+        HORA=`date +"%H%M%S"`
+\layout LyX-Code
+
+        UMBRAL="$LINEA;$PAIS;$TIPO;A;*;*;*"
+\layout LyX-Code
+
+        if existe_umbral "$UMBRAL" ; then
+\layout LyX-Code
+
+                echo "Ya existe un umbral con los datos ingresados."
+\layout LyX-Code
+
+                echo "Abortando..."
+\layout LyX-Code
+
+                put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+                  "Se trató de insertar un umbral repetido ($UMBRAL)" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+                return
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        # Genero el umbral
+\layout LyX-Code
+
+        buscar_id_umbral ID
+\layout LyX-Code
+
+        UMBRAL="$ID;$LINEA;$PAIS;$TIPO;A;$USER;$FECHA;$HORA"
+\layout LyX-Code
+
+        # Lo guardo
+\layout LyX-Code
+
+        echo "$UMBRAL" >> "$BASE_DIR/umbrales.param"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "El Umbral fue grabado con éxito"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        put_log "$LOGFILE" 
+\backslash 
+
+\layout LyX-Code
+
+          "aficonf" "Se inserto un nuevo umbral ($UMBRAL)" 
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+case_buscar () {
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Número de línea" "" LINEA
+\layout LyX-Code
+
+                #TODO Valido
+\layout LyX-Code
+
+                if ! validar_solo_numeros "$LINEA" ; then
+\layout LyX-Code
+
+                        echo "EL NUMERO TE LINEA SOLO DEBE" 
+\backslash 
+
+\layout LyX-Code
+
+                          "TENER DIGITOS"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$LINEA" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        DATOS=`cat "$BASE_DIR/umbrales.param" 
+\backslash 
+
+\layout LyX-Code
+
+          | grep "[0-9]*;$LINEA;[A-Z]*;[E,S];A"`
+\layout LyX-Code
+
+        if [ "$DATOS" == "" ] ; then
+\layout LyX-Code
+
+                echo ""
+\layout LyX-Code
+
+                echo "No se han encontrado Umbrales activos" 
+\backslash 
+
+\layout LyX-Code
+
+                  "para la linea $LINEA."
+\layout LyX-Code
+
+                echo "Abortando ..."
+\layout LyX-Code
+
+                echo ""
+\layout LyX-Code
+
+                put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+                  "No se han encontrado umbrales para la línea $LINEA" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        printf "%3s      %2s  %1s   %1s    %10s%8s       %6s
+\backslash 
+n" 
+\backslash 
+
+\layout LyX-Code
+
+          "ID" "Ciudad" "Tipo" "Estado" "Usuario" "Fecha" "Hora"
+\layout LyX-Code
+
+        OPCIONES="-1"
+\layout LyX-Code
+
+        for i in $DATOS ; do
+\layout LyX-Code
+
+                ID=`echo "$i" | cut -d ';' -f 1`
+\layout LyX-Code
+
+                CIUDAD=`echo "$i" | cut -d ';' -f 3`
+\layout LyX-Code
+
+                TIPO=`echo "$i" | cut -d ';' -f 4`
+\layout LyX-Code
+
+                ESTADO=`echo "$i" | cut -d ';' -f 5`
+\layout LyX-Code
+
+                USUARIO=`echo "$i" | cut -d ';' -f 6`
+\layout LyX-Code
+
+                FECHA=`echo "$i" | cut -d ';' -f 7`
+\layout LyX-Code
+
+                HORA=`echo "$i" | cut -d ';' -f 8`
+\layout LyX-Code
+
+                printf 
+\backslash 
+
+\layout LyX-Code
+
+"%3s      %2s      %1s      %1s      %10s      %8s      %6s
+\backslash 
+n" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$ID" "$CIUDAD" "$TIPO" "$ESTADO" "$USUARIO" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$FECHA" "$HORA"
+\layout LyX-Code
+
+                OPCIONES="$OPCIONES $ID"
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        preguntar "Cual desea borrar (-1 para salir)" "$OPCIONES" OPT
+\layout LyX-Code
+
+        if [ "$OPT" = "-1" ] ; then
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        echo "Borrando el registro $OPT ..."
+\layout LyX-Code
+
+        poner_estado_umbral "$OPT" "I"
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "No se ha eliminado elumbral de ID $OPT" "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "El Umbral fue eliminado con éxito"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# No permito correr 2 instancias de AFICONF
+\layout LyX-Code
+
+if is_lock "aficonf" ; then
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "Aficonf está corriendo actualmente."
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "Se ha intentado ejecutar aficonf cuando este estaba corriendo"
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+        exit 1
+\layout LyX-Code
+
+fi
+\layout LyX-Code
+
+lock "aficonf"
+\layout LyX-Code
+
+# Loop Principal
+\layout LyX-Code
+
+OPT="0"
+\layout LyX-Code
+
+while [ "$OPT" != "3" ] ; do 
+\layout LyX-Code
+
+        menu OPT
+\layout LyX-Code
+
+        case $OPT in
+\layout LyX-Code
+
+                "1") case_altas ;;
+\layout LyX-Code
+
+                "2") case_buscar ;;
+\layout LyX-Code
+
+        esac
+\layout LyX-Code
+
+done
+\layout LyX-Code
+
+unlock "aficonf"
+\layout Section
+
+UTIL.SH
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en bash.
+\layout Standard
+
+Sería equivalente a una biblioteca compartida, no es exactamente un comando
+ que se pueda ejecutar directamente sino que se incluye desde otros comandos.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Es un archivo con varias funciones generales, sirve para no duplicar código
+ común entre los varios scripts de bash.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Al ser de propósito general, no tiene ningún archivo de input específico,
+ aunque hay funciones que utilizan archivos, no se describen aquí sino en
+ los comandos que usan este archivo.
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+Al no ser un comando ejecutable, no aplica.
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Código fuente
+\layout LyX-Code
+
+#/bin/bash
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Los scrips que incluyan deben definir BASE_DIR
+\layout LyX-Code
+
+# antes de incluirme!
+\layout LyX-Code
+
+\layout LyX-Code
+
+LOCK_DIR="$BASE_DIR/lock"
+\layout LyX-Code
+
+# Lee del teclado un valor
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# parámetros :
+\layout LyX-Code
+
+#  $1 = Leyeda a mostrar de pregunta
+\layout LyX-Code
+
+#  $2 = Valor default por si el usuario no ingresa nada
+\layout LyX-Code
+
+#  $3 = Variable donde guardar el valor ingresado (o el default)
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+leer () {
+\layout LyX-Code
+
+        MSG=$1
+\layout LyX-Code
+
+        DEFAULT=$2
+\layout LyX-Code
+
+        read -p "$MSG [$DEFAULT] : " ALGO 
+\layout LyX-Code
+
+        # Si el usuario no ingresa nada
+\layout LyX-Code
+
+        # nos quedamos con el valor default
+\layout LyX-Code
+
+        if [ ! -z "$ALGO" ] ; then
+\layout LyX-Code
+
+                eval "$3=$ALGO"
+\layout LyX-Code
+
+        else
+\layout LyX-Code
+
+                eval "$3=$DEFAULT"
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Realiza una pregunta al usuario
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# parámetros :
+\layout LyX-Code
+
+#  $1 = Leyeda a mostrar de preguntar
+\layout LyX-Code
+
+#  $2 = string con las opciones validas
+\layout LyX-Code
+
+#  $3 = Variable donde guardar el valor ingresado
+\layout LyX-Code
+
+#  $4 = Valor por defecto si se apreta ENTER
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+preguntar () {
+\layout LyX-Code
+
+        PREGUNTA="$1"
+\layout LyX-Code
+
+        OPCIONES="$2"
+\layout LyX-Code
+
+        DEFAULT="$4"
+\layout LyX-Code
+
+        while true; do
+\layout LyX-Code
+
+                read -p "$PREGUNTA [$OPCIONES]: " RTA
+\layout LyX-Code
+
+                # Si me pasaron un default y la respuesta es vacía
+\layout LyX-Code
+
+                if [ -n "$DEFAULT" -a -z "$RTA" ]; then
+\layout LyX-Code
+
+                        # devuelvo default
+\layout LyX-Code
+
+                        RTA="$DEFAULT"
+\layout LyX-Code
+
+                        return 0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                # Escapeo el caracter '-' por '
+\backslash 
+-'
+\layout LyX-Code
+
+                RTA=$(echo $RTA | sed "s/
+\backslash 
+-/
+\backslash 
+
+\backslash 
+
+\backslash 
+-/")
+\layout LyX-Code
+
+                IS_OK=`echo "$OPCIONES" | grep "$RTA"`
+\layout LyX-Code
+
+                if [ ! -z "$IS_OK" ] && [ ! -z "$RTA" ] ; then
+\layout LyX-Code
+
+                        eval "$3=$RTA"
+\layout LyX-Code
+
+                        return 0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+validar_solo_numeros () {
+\layout LyX-Code
+
+        TEST=`echo "$1" | sed "s/[0-9]*//g"`
+\layout LyX-Code
+
+        if [ "$TEST" == "" ] ; then
+\layout LyX-Code
+
+                #Ok, son solo numeros
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        # ups, hay algo que no es un numero
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Crea un archivo de lock para un script
+\layout LyX-Code
+
+# Devuelve: 0 si ok, 1 si ya esta lockeado, 2 si no pudo crear lock.
+\layout LyX-Code
+
+# Uso: lock programa
+\layout LyX-Code
+
+lock () {
+\layout LyX-Code
+
+        # si ya esta loqueado, no lo vuelvo a crear
+\layout LyX-Code
+
+        is_lock "$1" && return 1
+\layout LyX-Code
+
+        # Si no puedo escribir en el dir de lock, da error
+\layout LyX-Code
+
+        [ -w "$LOCK_DIR" ] || return 2
+\layout LyX-Code
+
+        echo $$ > "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+        return 0
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Desbloquea el script
+\layout LyX-Code
+
+# Uso: unlock programa
+\layout LyX-Code
+
+unlock () {
+\layout LyX-Code
+
+        rm -rf "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+                        
+\layout LyX-Code
+
+# Consulta si un script esta lockeado
+\layout LyX-Code
+
+# Uso: is_lock programa
+\layout LyX-Code
+
+is_lock () {
+\layout LyX-Code
+
+        if [ -e "$LOCK_DIR/$1.pid" ] ; then
+\layout LyX-Code
+
+                # Lock file encontrado!
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        # No hay lock file!
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Obtiene el pid de un programa lockeado
+\layout LyX-Code
+
+# Uso: lock_pid programa
+\layout LyX-Code
+
+lock_pid()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        is_lock "$1" && cat "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Verifica que un valor este entre otros 2
+\layout LyX-Code
+
+# $1 pertecezca a [$2,$3]
+\layout LyX-Code
+
+# $1 Numero a validar
+\layout LyX-Code
+
+# $2 Cota inferior 
+\layout LyX-Code
+
+# $3 Cota superior
+\layout LyX-Code
+
+validar_rango(){
+\layout LyX-Code
+
+        if [ "$1" -ge "$2" ] && [ "$1" -le "$3" ]; then
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        else 
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Muestra mensaje y sale con código de error
+\layout LyX-Code
+
+# Uso: die mensaje [código de error = 1]
+\layout LyX-Code
+
+die()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        echo "$1" >&2
+\layout LyX-Code
+
+        exit ${2:-1}
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Imprime mensaje por salida de error
+\layout LyX-Code
+
+# Uso: perr mensajes
+\layout LyX-Code
+
+perr()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        echo $@ >&2
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Pone un MSG en el log
+\layout LyX-Code
+
+# Parametros :
+\layout LyX-Code
+
+#  $1 = Archivo del log
+\layout LyX-Code
+
+#  $2 = Comando
+\layout LyX-Code
+
+#  $3 = Mensaje
+\layout LyX-Code
+
+#  $4 = Tamaño maximo
+\layout LyX-Code
+
+put_log() {
+\layout LyX-Code
+
+        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+        echo "$fecha $USER $2:
+\backslash 
+"$3
+\backslash 
+"" >> $1
+\layout LyX-Code
+
+        clean_log "$1" "$4"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Trunca un archivo de log si pasa el tamaño máximo.
+\layout LyX-Code
+
+# Uso: clean_log log_filename max_log_size_bytes
+\layout LyX-Code
+
+clean_log()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        LOGFILE="$1"
+\layout LyX-Code
+
+        LOGSIZE="$2"
+\layout LyX-Code
+
+        # Archivo temporal
+\layout LyX-Code
+
+        tmp=`dirname "$LOGFILE"`"/`basename $0`.$$.temp"
+\layout LyX-Code
+
+        # Verifico que el logfile no se pase del tamaño maximo
+\layout LyX-Code
+
+        tam=`stat -c '%s' "$LOGFILE"`
+\layout LyX-Code
+
+        # Si se paso del maximo dejo las ultimas 100 lineas
+\layout LyX-Code
+
+        if [ "$tam" -ge "$LOGSIZE" ]; then
+\layout LyX-Code
+
+                tail -n 100 "$LOGFILE" > "$tmp"
+\layout LyX-Code
+
+                mv "$tmp" "$LOGFILE"
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout Section
+
+AFIMONIO_DAEMON.SH
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en 
+\family typewriter 
+bash
+\family default 
+.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Sirve para correr 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ en segundo plano, desasociado de la terminal.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
+ redireccionarle el archivo 
+\family typewriter 
+oridesti.txt
+\family default 
+.
+ De la entrada estándar toma los códigos de origen y destino.
+ Cada código debe encontrarse en una línea y al comienzo de ésta.
+ Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
+ compatibilidad con el archivo oridesti.txt).
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Crea una cantidad 
+\family typewriter 
+N
+\family default 
+ (especificada por el usuario) de archivos con nombre y formato de 
+\emph on 
+Archivo de Llamadas
+\emph default 
+ en el directorio actual.
+ Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
+mente (respetando el formato mencionado y con valores racionales).
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+La invocación es al estilo SysV, tomando como parámetro la acción a realizar,
+ que puede ser:
+\layout Description
+
+start Arranca el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Description
+
+stop Detiene el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Description
+
+status Indica si 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ está corriendo o no.
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Al comienzo del script, abajo de 
+\family typewriter 
+Configuración
+\family default 
+, se pueden cambiar algunas variables:
+\layout Description
+
+WAIT Cantidad de segundos a esperar para que arranque o se detenga 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ antes de asumir un error.
+\layout Description
+
+DAEMON Nombre del programa a ejecutar.
+ Este programa es lo suficientemente genérico como para correr cualquier
+ comando en modo 
+\emph on 
+daemon
+\emph default 
+, por eso se provee una variable de configuración para cambiar el comando
+ a ejecutar.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh start
+\layout Standard
+
+Arranca el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh stop
+\layout Standard
+
+Detiene el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh status
+\layout Standard
+
+Si 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ está corriendo lo indica con un mensaje y muestra su PID.
+ Si no está corriendo da otro mensaje indicándolo.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh
+\layout Standard
+
+Da un mensaje de ayuda.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/bin/bash
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Configuración
+\layout LyX-Code
+
+WAIT=10
+\layout LyX-Code
+
+DAEMON=afimonio
+\layout LyX-Code
+
+\layout LyX-Code
+
+# --------------- SCRIPT ---------------------
+\layout LyX-Code
+
+BASE_DIR="$HOME/.antifraude"
+\layout LyX-Code
+
+.
+ "$BASE_DIR/conf/$DAEMON.conf"
+\layout LyX-Code
+
+.
+ "$BASE_DIR/util.sh"
+\layout LyX-Code
+
+\layout LyX-Code
+
+ayuda () {
+\layout LyX-Code
+
+        perr "Parámetros válidos : start, stop, status"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+case "$1" in
+\layout LyX-Code
+
+        "start")
+\layout LyX-Code
+
+                echo -n "Iniciando demonio '$DAEMON' en modo daemon "
+\layout LyX-Code
+
+                if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo " ERROR!"
+\layout LyX-Code
+
+                        perr "$DAEMON ya está corriendo" 
+\backslash 
+
+\layout LyX-Code
+
+                             "(PID=`lock_pid $DAEMON`)."
+\layout LyX-Code
+
+                        exit 1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                nohup "$AFIM_BINDIR/$DAEMON" > /dev/null &
+\layout LyX-Code
+
+                for i in `seq $WAIT`; do
+\layout LyX-Code
+
+                        if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                                echo " OK! (PID=`lock_pid $DAEMON`)"
+\layout LyX-Code
+
+                                exit 0
+\layout LyX-Code
+
+                        fi
+\layout LyX-Code
+
+                        echo -n '.'
+\layout LyX-Code
+
+                        sleep 1;
+\layout LyX-Code
+
+                done
+\layout LyX-Code
+
+                # Tardó más de 5 segundos en arrancar, algo anda mal...
+\layout LyX-Code
+
+                echo "ERROR!"
+\layout LyX-Code
+
+                perr "$DAEMON tardó más de $WAIT segundos en arrancar,"
+\backslash 
+
+\layout LyX-Code
+
+                     "probablemente haya algún problema."
+\layout LyX-Code
+
+                exit 1
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        "stop")
+\layout LyX-Code
+
+                echo -n "Parando el demonio '$DAEMON' "
+\layout LyX-Code
+
+                if ! is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo " ERROR!"
+\layout LyX-Code
+
+                        perr "$DAEMON no esta corriendo."
+\layout LyX-Code
+
+                        exit 1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                kill `lock_pid $DAEMON`
+\layout LyX-Code
+
+                for i in `seq $WAIT`; do
+\layout LyX-Code
+
+                        if ! is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                                echo " OK!"
+\layout LyX-Code
+
+                                exit 0
+\layout LyX-Code
+
+                        fi
+\layout LyX-Code
+
+                        echo -n '.'
+\layout LyX-Code
+
+                        sleep 1;
+\layout LyX-Code
+
+                done
+\layout LyX-Code
+
+                # Tardó más de 5 segundos en parar, algo anda mal...
+\layout LyX-Code
+
+                echo "ERROR!"
+\layout LyX-Code
+
+                perr "$DAEMON tardó más de $WAIT segundos en parar," 
+\backslash 
+
+\layout LyX-Code
+
+                     "probablemente haya algún problema."
+\layout LyX-Code
+
+                exit 1
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        "status")
+\layout LyX-Code
+
+                if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo "$DAEMON está corriendo actualmente" 
+\backslash 
+
+\layout LyX-Code
+
+                             "(PID=`lock_pid $DAEMON`)."
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        echo "$DAEMON no está corriendo."
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        *) ayuda ;;
+\layout LyX-Code
+
+esac
+\layout Section
+
+CALLGEN
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en 
+\family typewriter 
+perl
+\family default 
+.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Sirve para realizar lotes de prueba con gran cantidad de entradas y variaciones
+ de forma rápida y cómoda.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
+ redireccionarle el archivo 
+\family typewriter 
+oridesti.txt
+\family default 
+.
+ De la entrada estándar toma los códigos de origen y destino.
+ Cada código debe encontrarse en una línea y al comienzo de ésta.
+ Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
+ compatibilidad con el archivo oridesti.txt).
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Crea una cantidad 
+\family typewriter 
+N
+\family default 
+ (especificada por el usuario) de archivos con nombre y formato de 
+\emph on 
+Archivo de Llamadas
+\emph default 
+ en el directorio actual.
+ Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
+mente (respetando el formato mencionado y con valores racionales).
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+El comando toma 3 parámetros 
+\series bold 
+opcionales
+\series default 
+:
+\layout LyX-Code
+
+./callgen [cant_archivos [min_lineas [max_lineas]]]
+\layout Standard
+
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="4" columns="3">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Parámetro
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Descripción
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Default
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+cant_archivos
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Cantidad de archivos a generar
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+min_lineas
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Mínima cantidad de lineas en un archivo
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1000
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+max_linaes
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Máxima cantidad de lineas en un archivo
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5000
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Pueden cambiarse los valores por defecto editando el código fuente del comando,
+ en la sección de configuración que se encuentra al comienzo del mismo.
+ También puede cambiarse el mínimo y máximo año (por defecto 1999 y 2004)
+ y el mínimo y máximo código de central (por defecto 0000 y 9999).
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen
+\layout Paragraph
+
+
+\series medium 
+Se escriben por entrada estándar los códigos de origen/destino, se presiona
+\family typewriter 
+\series default 
+Ctrl-D
+\family default 
+\series medium 
+ para cerrar el descriptor de archivo de la entrada estándar y se generan
+ 10 archivos con entre 1000 y 5000 líneas cada uno.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 2 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 2 archivos con entre 1000 y 5000 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 5 10 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 5 archivos con entre 10 y 5000 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 50 10 50 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 50 archivos con entre 10 y 50 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/usr/bin/perl -w
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Generador aleatorio de archivos de llamadas
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Leandro Lucarella - dom oct 17 18:37:05 ART 2004
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Bajo licencia GPL.
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Uso:
+\layout LyX-Code
+
+#      ./callgen [cant_archivos [min_lineas [max_lineas]]]
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# cant_archivos Cantidad de archivos a generar.
+\layout LyX-Code
+
+# min_lines     Mínima cantidad de líneas que puede tener un archivo.
+\layout LyX-Code
+
+# max_lines     Máxima cantidad de líneas que puede tener un archivo.
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Por la entrada estándar debe recibir los códigos de países para
+\layout LyX-Code
+
+# origen y/o destino.
+ Toma los dos primeros caracteres por línea como
+\layout LyX-Code
+
+# un código, ignorando el resto, de manera que se puede hacer:
+\layout LyX-Code
+
+#       cat oridesti.txt | ./gencall
+\layout LyX-Code
+
+# Configuración
+\layout LyX-Code
+
+$CANT_ARCHS = 10;
+\layout LyX-Code
+
+$MIN_LINEAS = 1000;
+\layout LyX-Code
+
+$MAX_LINEAS = 5000;
+\layout LyX-Code
+
+$MIN_ANIO   = "1999";
+\layout LyX-Code
+
+$MAX_ANIO   = "2004";
+\layout LyX-Code
+
+$MIN_COD    = "0000";
+\layout LyX-Code
+
+$MAX_COD    = "9999";
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Variables globales
+\layout LyX-Code
+
+our @codes; # Códigos de origen/destino
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Funciones
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ load_codes() - Obtiene códigos de origen/destino de la entrada
+\layout LyX-Code
+
+#                   estándar
+\layout LyX-Code
+
+# Uso: load_codes()
+\layout LyX-Code
+
+sub load_codes()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        push(@codes, substr($_, 0, 2)) while (<STDIN>);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ get_rnd_code() - Obtiene un códigos de origen/destino al azar
+\layout LyX-Code
+
+# Uso: get_rnd_code()
+\layout LyX-Code
+
+sub get_rnd_code()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my $cant = @codes;
+\layout LyX-Code
+
+        return $codes[rnd($cant-1)];
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ rnd() - Genera números aleatorios
+\layout LyX-Code
+
+# Uso: rnd(MAX)      - genera número de 0 a MAX (inclusive)
+\layout LyX-Code
+
+#      rnd(MIN, MAX) - genera número de MIN a MAX (inclusive)
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Nota: respeta el tamaño del campo más chico, es decir, si se usa
+\layout LyX-Code
+
+#       rnd 01 250, el número siempre tendrá al menos 2 dígitos
+\layout LyX-Code
+
+#       rellenados con ceros, como 04, 28, 123, 08, etc
+\layout LyX-Code
+
+sub rnd($;$)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my ($ini, $fin) = @_;
+\layout LyX-Code
+
+        if (!$fin)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $fin = $ini;
+\layout LyX-Code
+
+                $ini = 0;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        return sprintf('%0'.length($ini).'d', $ini + rand()
+\layout LyX-Code
+
+          * ($fin - $ini + 1));
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Tipos de campos
+\layout LyX-Code
+
+sub aaaa() { return rnd($MIN_ANIO, $MAX_ANIO); } # año
+\layout LyX-Code
+
+sub mm()   { return rnd("01", 12); }             # mes
+\layout LyX-Code
+
+sub dd()   { return rnd("01", 28); }             # día
+\layout LyX-Code
+
+sub hh()   { return rnd("00", 23); }             # hora
+\layout LyX-Code
+
+sub MM()   { return rnd("00", 59); }             # minutos
+\layout LyX-Code
+
+# código de central telefónica
+\layout LyX-Code
+
+sub DDDD() { return rnd($MIN_COD, $MAX_COD); }
+\layout LyX-Code
+
+# caracter aleatorio
+\layout LyX-Code
+
+sub char() { return chr(rnd(65, 90)); }   
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ line() - Genera una línea del archivo
+\layout LyX-Code
+
+sub line()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my $f_linea   = rnd(100000, 99999999);
+\layout LyX-Code
+
+        my $f_minutos = rnd(1, 150);
+\layout LyX-Code
+
+        my $f_fecha   = aaaa().mm().dd();
+\layout LyX-Code
+
+        my $f_hora    = dd().hh().MM();
+\layout LyX-Code
+
+        my ($f_tipo, $f_orig, $f_dest) = ('', '', '');
+\layout LyX-Code
+
+        if (rnd(1) == 1)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $f_tipo = 'E';
+\layout LyX-Code
+
+                $f_orig = get_rnd_code();
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        else
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $f_tipo = 'S';
+\layout LyX-Code
+
+                $f_dest = get_rnd_code();
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        my $f_prest = char().char().char().char().char().
+\layout LyX-Code
+
+                      char().char().char().char();
+\layout LyX-Code
+
+        return "$f_linea;$f_minutos;$f_fecha;$f_hora;".
+\layout LyX-Code
+
+               "$f_tipo;$f_dest;$f_orig;$f_prest";
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ gen() - Genera un archivo con entre MIN y MAX llamadas
+\layout LyX-Code
+
+# Uso: gen(MIN, MAX)
+\layout LyX-Code
+
+sub gen($$)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my ($ini, $fin) = @_;
+\layout LyX-Code
+
+        my $file = aaaa().mm().dd().hh().MM().'.'.DDDD();
+\layout LyX-Code
+
+        # Mientras exista uno, buscamos un nuevo nombre.
+\layout LyX-Code
+
+        $file = aaaa().mm().dd().hh().MM().'.'.DDDD()
+\layout LyX-Code
+
+          while (-e $file);
+\layout LyX-Code
+
+        open(FH, ">$file")
+\layout LyX-Code
+
+          or die("No puedo abrir el archivo $file!
+\backslash 
+n");
+\layout LyX-Code
+
+        for (my $i = rnd($ini, $fin); $i > 0; --$i)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                print FH line()."
+\backslash 
+n";
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Programa
+\layout LyX-Code
+
+srand;
+\layout LyX-Code
+
+my $cant = $ARGV[0] ? $ARGV[0] : $CANT_ARCHS;
+\layout LyX-Code
+
+load_codes();
+\layout LyX-Code
+
+for (my $i = 0; $i < $cant; ++$i)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        gen($ARGV[1] ? $ARGV[1] : $MIN_LINEAS,
+\layout LyX-Code
+
+            $ARGV[2] ? $ARGV[2] : $MAX_LINEAS);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# vim: set fdm=marker ts=4 sw=4 :
+\layout Chapter
+
+Archivos
+\layout Section
+
+Archivos del Enunciado
+\layout Subsection
+
+
+\family typewriter 
+<comando>.log
+\layout Standard
+
+Los archivos de log generados por los distintos comandos, presentan todos
+ la misma estructura de registro que se detalla a continuación: 
+\family typewriter 
+YYYYMMDD-hhmm $usuario $comando: ¨$Mensaje¨
+\layout Subsection
+
+
+\family typewriter 
+oridesti.txt
+\layout Standard
+
+En este archivo se tienen los origenes y destinos en base a los cuales hemos
+ generados los archivos de llamada y los umbrales.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de oridesti.txt
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="2" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Código
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Descripción
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\end_inset 
+
+
+\layout Subsection
+
+
+\family typewriter 
+umbrales.param
+\layout Standard
+
+Este archivo posee los umbrales de llamadas de los cuales se valdra el antifraud
+e.pl para emitir o no alarmas durante el proceso de los archivos de llamadas.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de umbrales.param
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Id del registro
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, número secuencial >= 1
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Número de línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Origen/Destino
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, valores posibles segun oridesti.txt
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tipo de llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 caracter, E = Entrante, S = Salida
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Estado
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 caracter, A = Activo, I = Inactivo
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Usuario
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres = login del user que graba el reg
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Fecha
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+8 caracteres, formato aaaammdd
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Hora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6 caracteres, formato hhmmss, hora actual
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\end_inset 
+
+
+\layout Subsection
+
+
+\family typewriter 
+<archivo de llamada>
+\layout Standard
+
+Estos archivos son los que el antifraude procesará en busca de matchs contra
+ los umbrales.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de un archivo de llamadas
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<column alignment="center" valignment="top" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Número de línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Cantidad de Minutos
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Fecha de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+8 caracteres, formato aaaammdd
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Hora de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6 caracteres, formato hhmmss
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tipo de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 carácter, E = Entrante, S = Salida
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Destino
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, solo informado en llamadas salientes
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Origen
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, solo informado en llamadas entrantes
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Prestadora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
 
-Código Fuente
 \layout Standard
 
 \layout Standard
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+N caracteres
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
 
 
-CALLGEN
-\layout Standard
+\end_inset 
 
 
 
 
-\series bold 
-Tipo de comando:
-\series default 
- Auxiliar, escrito en PERL
-\layout Subsubsection
+\end_inset 
 
 
-Justificación de su uso
-\layout Standard
 
 
-Sirve para realizar lotes de prueba con gran cantidad de entradas y variaciones
- de forma rápida y cómoda.
-\layout Subsubsection
+\layout Subsection
 
 
-Archivos de Input
-\layout Standard
 
 
-Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
- redireccionarle el archivo 
 \family typewriter 
 \family typewriter 
-oridesti.txt
-\family default 
-.
- De la entrada estándar toma los códigos de origen y destino.
- Cada código debe encontrarse en una línea y al comienzo de ésta.
- Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
- compatibilidad con el archivo oridesti.txt).
-\layout Subsubsection
-
-Archivos de Output
+alarmas.txt
 \layout Standard
 
 \layout Standard
 
-Crea una cantidad N (especificada por el usuario) de archivos con nombre
- y formato de Archivo de Llamadas en el directorio actual.
- Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
-mente (respetando el formato mencionado y con valores racionales).
-\layout Subsubsection
-
-Parámetros
+En este archivo el antifraude irá dejando registro de las alarmas emitidas
+ en base a registros que han tenido un match contra los umbrales.
 \layout Standard
 
 \layout Standard
 
-El comando toma 3 parámetros 
-\series bold 
-opcionales
-\series default 
-:
-\layout LyX-Code
-
-./callgen [cant_archivos [min_lineas [max_lineas]]]
-\layout LyX-Code
-
 
 \begin_inset Float table
 
 \begin_inset Float table
+placement H
 wide false
 wide false
-collapsed false
+collapsed true
 
 \layout Caption
 
 
 \series bold 
 
 \layout Caption
 
 
 \series bold 
-Parámetros del comando CALLGEN
+Estructura de alarmas.txt
 \layout Standard
 \align center 
 
 \begin_inset  Tabular
 \layout Standard
 \align center 
 
 \begin_inset  Tabular
-<lyxtabular version="3" rows="4" columns="3">
+<lyxtabular version="3" rows="10" columns="2">
 <features>
 <column alignment="center" valignment="top" leftline="true" width="0">
 <features>
 <column alignment="center" valignment="top" leftline="true" width="0">
-<column alignment="center" valignment="top" leftline="true" width="0">
 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
 <row topline="true" bottomline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
 <row topline="true" bottomline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
@@ -397,19 +4319,25 @@ Par
 
 \layout Standard
 
 
 \layout Standard
 
+Prestadora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
 
-\series bold 
-Parámetro
+\layout Standard
+
+N caracteres, campo 'Prestadora', archivo de llamadas
 \end_inset 
 </cell>
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-
-\series bold 
-Descripción
+Central Telefónica
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -417,9 +4345,7 @@ Descripci
 
 \layout Standard
 
 
 \layout Standard
 
-
-\series bold 
-Default
+4 caracteres, obtenido a partir del archivo de llamadas
 \end_inset 
 </cell>
 </row>
 \end_inset 
 </cell>
 </row>
@@ -429,15 +4355,25 @@ Default
 
 \layout Standard
 
 
 \layout Standard
 
-cant_archivos
+Número de Línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, campo 'Numero de Linea' , archivo de llamadas
 \end_inset 
 </cell>
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-Cantidad de archivos a generar
+Cantidad de minutos
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -445,7 +4381,7 @@ Cantidad de archivos a generar
 
 \layout Standard
 
 
 \layout Standard
 
-10
+N caracteres, campo 'Cant de Minutos', archivo de llamadas
 \end_inset 
 </cell>
 </row>
 \end_inset 
 </cell>
 </row>
@@ -455,41 +4391,43 @@ Cantidad de archivos a generar
 
 \layout Standard
 
 
 \layout Standard
 
-min_lineas
+Regla Aplicada
 \end_inset 
 </cell>
 \end_inset 
 </cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 \begin_inset Text
 
 \layout Standard
 
-Mínima cantidad de lineas en un archivo
+N caracteres, campo 'Id de registro', umbrales.param
 \end_inset 
 </cell>
 \end_inset 
 </cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 \begin_inset Text
 
 \layout Standard
 
-1000
+Fecha de llamada
 \end_inset 
 </cell>
 \end_inset 
 </cell>
-</row>
-<row topline="true" bottomline="true">
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 \begin_inset Text
 
 \layout Standard
 
-max_lines
+8 caracteres, campo 'Fecha de llamada', archivo de llamadas
 \end_inset 
 </cell>
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-Máxima cantidad de lineas en un archivo
+Hora de llamada
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 
 \layout Standard
 
 
 \layout Standard
 
-5000
+6 caracteres, campo 'Hora de llamada', archivo de llamadas
 \end_inset 
 </cell>
 </row>
 \end_inset 
 </cell>
 </row>
-</lyxtabular>
-
-\end_inset 
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
 
+\layout Standard
 
 
+Usuario
 \end_inset 
 \end_inset 
-
-
-\layout LyX-Code
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
 \layout Standard
 
 
 \layout Standard
 
+N caracteres, siempre login del usuario que graba el reg
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
 
-\series bold 
-NOTA:
-\series default 
- Pueden cambiarse los valores por defecto editando el código fuente del
- comando, en la sección de configuración que se encuentra al comienzo del
- mismo.
- También puede cambiarse el mínimo y máximo año (por defecto 1999 y 2004)
- y el mínimo y máximo código de central (por defecto 0000 y 9999).
-\layout Subsubsection
-
-Ejemplos de invocación
-\layout Paragraph
-
-./callgen
-\layout Paragraph
-
+\layout Standard
 
 
-\series medium 
-Se escriben por entrada estándar los códigos de origen/destino, se presiona
- Ctrl-D para cerrar el descriptor de archivo de la entrada estándar y se
- generan 10 archivos con entre 1000 y 5000 líneas cada uno.
-\layout Paragraph
+Fecha
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
 
-./callgen 2 < oridesti.txt
-\layout Paragraph
+\layout Standard
 
 
+8 caracteres, formato aaaammdd, fecha actual
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
 
-\series medium 
-Genera 2 archivos con entre 1000 y 5000 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Paragraph
+\layout Standard
 
 
-./callgen 5 10 < oridesti.txt
-\layout Paragraph
+Hora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
 
+\layout Standard
 
 
-\series medium 
-Genera 5 archivos con entre 10 y 5000 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Paragraph
+6 caracteres formato hhmmss, hora actual
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
 
 
-./callgen 50 10 50 < oridesti.txt
-\layout Paragraph
+\end_inset 
 
 
 
 
-\series medium 
-Genera 50 archivos con entre 10 y 50 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Subsubsection
+\end_inset 
 
 
-Código Fuente
-\layout Standard
 
 
-Copy Paste cuando este cerrado.
 \layout Section
 
 \layout Section
 
-Archivos
-\layout Subsection
-
-Archivos del Enunciado
-\layout Standard
-
-[ Por cada uno se debe poner nombre y detallar su estructura interna ]
+Archivos Auxiliares
 \layout Subsection
 
 \layout Subsection
 
-Archivos Auxiliares
-\layout Subsubsection
 
 
+\family typewriter 
 afimonio.conf
 \layout Standard
 
 afimonio.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/afimonio.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/afimonio.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 afimonio
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
 \family typewriter 
 afimonio
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
-\layout Subsubsection
+\layout Subsection
 
 
+
+\family typewriter 
 antifraude.conf
 \layout Standard
 
 antifraude.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/antifraude.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/antifraude.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 antifraude.pl
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
 \family typewriter 
 antifraude.pl
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
-\layout Subsubsection
+\layout Subsection
+
 
 
+\family typewriter 
 aficonf.conf
 \layout Standard
 
 aficonf.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/aficonf.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/aficonf.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 aficonf
 \family default 
 \family typewriter 
 aficonf
 \family default 
@@ -621,10 +4562,19 @@ aficonf
 
 Estos archivos fueron creados para que los diferentes scripts tengan un
  lugar común donde buscar esa información para salvar el problema comentado
 
 Estos archivos fueron creados para que los diferentes scripts tengan un
  lugar común donde buscar esa información para salvar el problema comentado
- en el punto 1.2.
+ en el punto 
+\begin_inset LatexCommand \vref{sec:Problemas-relevantes}
+
+\end_inset 
+
+.
 \layout Subsection
 
 \layout Subsection
 
-Set de Prueba (testcalls.tar.gz)
+Set de Prueba (
+\family typewriter 
+testcalls.tar.gz
+\family default 
+)
 \layout Standard
 
 Para probar el comportamiento del sistema, se preparo un set de prueba distribui
 \layout Standard
 
 Para probar el comportamiento del sistema, se preparo un set de prueba distribui
@@ -632,20 +4582,31 @@ do en el archivo
 \family typewriter 
 testcalls.tar.gz
 \family default 
 \family typewriter 
 testcalls.tar.gz
 \family default 
-, situado en el directorio /INST, del paquete de instalación.
+, situado en el directorio 
+\family typewriter 
+/inst
+\family default 
+, del paquete de instalación.
  El set de prueba se copia automáticamente en el momento en que se instale
  el componente 
  El set de prueba se copia automáticamente en el momento en que se instale
  el componente 
+\family typewriter 
 \series bold 
 \series bold 
-ANTIFRAUDE
+antifraude
+\family default 
 \series default 
 , dejando el escenario listo para procesarlos en el momento en que sea arrancado
  el 
 \series default 
 , dejando el escenario listo para procesarlos en el momento en que sea arrancado
  el 
+\family typewriter 
 \series bold 
 \series bold 
-AFIMONIO 
+afimonio
+\family default 
 \series default 
 o bien ejecutando el 
 \series default 
 o bien ejecutando el 
+\family typewriter 
 \series bold 
 \series bold 
-ANTIFRAUDE
+antifraude
+\family default 
 \series default 
  en forma manual.
 \layout Standard
 \series default 
  en forma manual.
 \layout Standard
@@ -658,21 +4619,35 @@ Este set de prueba consta de
 \layout Itemize
 
 14 archivos de llamadas generados con el 
 \layout Itemize
 
 14 archivos de llamadas generados con el 
+\family typewriter 
 \series bold 
 \series bold 
-CALLGEN
+callgen
+\family default 
 \series default 
 , con entre 1000 y 5000 registros cada uno, y fecha en el rango año 1999
 \series default 
 , con entre 1000 y 5000 registros cada uno, y fecha en el rango año 1999
- 2004.
a 2004.
 \layout Itemize
 
 \layout Itemize
 
-1 archivo de llamadas con registros validos y otros no validos.
+1 archivo de llamadas con registros válidos y otros no válidos.
 \layout Itemize
 
 1 archivo con nombre válido según el formato YYYYMMDDhhmm.nnnn, pero con
 \layout Itemize
 
 1 archivo con nombre válido según el formato YYYYMMDDhhmm.nnnn, pero con
- texto dentro suyo, el cual es rechazado por Antifraude.
+ contenido inválido, el cual es rechazado por 
+\family typewriter 
+\series bold 
+antifraude
+\family default 
+\series default 
+.
 \layout Itemize
 
 \layout Itemize
 
-1 archivo con nombre no válido rechazado en instancia previa por el Afimonio.
+1 archivo con nombre no válido rechazado en instancia previa por 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
 \layout Standard
 
 Se describen en la siguiente tabla, los archivos y registros que disparan
 \layout Standard
 
 Se describen en la siguiente tabla, los archivos y registros que disparan
@@ -682,8 +4657,9 @@ Se describen en la siguiente tabla, los archivos y registros que disparan
 
 
 \begin_inset Float table
 
 
 \begin_inset Float table
+placement H
 wide false
 wide false
-collapsed false
+collapsed true
 
 \layout Caption
 
 
 \layout Caption
 
@@ -717,7 +4693,8 @@ Archivo
 
 
 \series bold 
 
 
 \series bold 
-Linea Nro
+Nro.
+ Línea
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -727,7 +4704,7 @@ Linea Nro
 
 
 \series bold 
 
 
 \series bold 
-Matched Umbral
+Umbral
 \end_inset 
 </cell>
 </row>
 \end_inset 
 </cell>
 </row>
@@ -1337,85 +5314,116 @@ Close match umbral 22, difiere tipo de llamada
 \end_inset 
 
 
 \end_inset 
 
 
-\layout Paragraph
+\layout Subsubsection
 
 
-Archivo 199908220733.4515
+Archivo 
+\family typewriter 
+199908220733.4515
 \layout Paragraph
 
 
 \series medium 
 \layout Paragraph
 
 
 \series medium 
-Posee registros no validos detallados a continuación.
- Los registros se contabilizan de 0 a N (Linea 1 = Reg 0)
-\layout Itemize
+Posee registros no válidos detallados a continuación.
+ Los registros se contabilizan de 0 a N (Línea 1 = Reg 0)
+\layout Description
 
 
+Registro\SpecialChar ~
 
 \series bold 
 
 \series bold 
-Registro 3
+3
 \series default 
 \series default 
- -> Posee un 9no campo 'Bogus'
-\layout Itemize
+ Posee un 9no campo 
+\emph on 
+bogus
+\layout Description
 
 
+Registro\SpecialChar ~
 
 \series bold 
 
 \series bold 
-Registro 27
+27
 \series default 
 \series default 
- -> Posee un 9no campo 'Bogus'
-\layout Itemize
+ Posee un 9no campo 
+\emph on 
+bogus
+\layout Description
 
 
+Registro\SpecialChar ~
 
 \series bold 
 
 \series bold 
-Registro 31
+31
 \series default 
 \series default 
- -> Posee un tipo de llamada 'W' no valida
-\layout Itemize
+ Posee un tipo de llamada 
+\family typewriter 
+W
+\family default 
+ no valida
+\layout Description
 
 
+Registro\SpecialChar ~
 
 \series bold 
 
 \series bold 
-Registro 41
+41
 \series default 
 \series default 
- -> El numero de linea (campo1) no es numerico, es un string 'ABCD'
-\layout Itemize
+ El número de línea (campo1) no es numérico, es un string 
+\family typewriter 
+'ABCD'
+\layout Description
 
 
+Registro\SpecialChar ~
 
 \series bold 
 
 \series bold 
-Registro 52
+52
 \series default 
 \series default 
-> Tiene insuficiente cantidad de campos (siete)
Tiene cantidad de campos insuficiente (siete)
 \layout Standard
 
 \layout Standard
 
-Estos registros emitirán errores plasmados en el antifraude.log.
- Para verificar esto, realizar un search en el logfile, sobre el nombre
- del archivo, y ubicarse en el sector donde se indica el comienzo del procesamie
-nto del mismo con ¨
+Estos registros emitirán errores plasmados en el 
+\family typewriter 
+antifraude.log
+\family default 
+.
+ Para verificar esto, realizar una búsqueda en el log, sobre el nombre del
+ archivo, y ubicarse en el sector donde se indica el comienzo del procesamiento
+ del mismo con ¨
 \family typewriter 
 Inicio proceso de: 199908220733.4515
 \family default 
 ¨.
 \family typewriter 
 Inicio proceso de: 199908220733.4515
 \family default 
 ¨.
-\layout Paragraph
+\layout Subsubsection
 
 
-Archivo 200412010000.6666
+Archivo 
+\family typewriter 
+200412010000.6666
 \layout Paragraph
 
 
 \series medium 
 Es un archivo de texto el cual pasa el control de Afimonio, pero luego sus
  lineas son descartadas por antifraude y dicho error emitido en el antifraude.log
 \layout Paragraph
 
 
 \series medium 
 Es un archivo de texto el cual pasa el control de Afimonio, pero luego sus
  lineas son descartadas por antifraude y dicho error emitido en el antifraude.log
-\layout Paragraph
+\layout Subsubsection
 
 
-Archivo 200223.1234
+Archivo 
+\family typewriter 
+200223.1234
 \layout Paragraph
 
 
 \series medium 
 El nombre del archivo no es conforme al formato de nombre estipulado en
 \layout Paragraph
 
 
 \series medium 
 El nombre del archivo no es conforme al formato de nombre estipulado en
- el TP y el mismo es rechazado de antemano por Afimonio.
-\layout Section
+ el TP y el mismo es rechazado de antemano por 
+\family typewriter 
+\series default 
+afimonio
+\family default 
+\series medium 
+.
+\layout Chapter
 
 Apéndice A
 
 Apéndice A
-\layout Standard
+\layout Comment
 
 
-(Esto deberia ser una hoja aparte que solo diga 1.6 Apéndice A) y las hojas
+Esto deberia ser una hoja aparte que solo diga 1.6 Apéndice A) y las hojas
  posteriores son las páginas 3 en adelante del PDF oficial de la catedra,
  sacando la parte de archivos.
  posteriores son las páginas 3 en adelante del PDF oficial de la catedra,
  sacando la parte de archivos.
- 3-15 más precisamente es lo que iria).
+ 3-15 más precisamente es lo que iria.
 \the_end
 \the_end