Blog de desarrolladores Abanq
Noticias y comentario de los desarrolladores. Bienvenido al blog

6/2/2009

Por fin: Un editor gráfico de informes

— Jesús @ 6:53 am

Durante mucho tiempo AbanQ ha carecido de un editor gráfico de informes realmente usable. El editor de Kugar resulta demasiado básico y no responde a las mejoras que desde InfoSiAL hemos ido haciendo estos años al motor de informes de AbanQ. Así, para editar o crear informes había que hacerlo peleando directamente con los ficheros xml con formato kut en un editor de texto plano. Esta forma de trabajo es lenta y pesada, pero es lo que había hasta este momento.

En InfoSiAL llevamos meses trabajando y probando un nuevo sistema de creación y edición de informes basado en el uso del editor de interfaces gráficos de QT en su versión 4: QT4 Designer. Este editor es la nueva versión del famoso editor de formularios de AbanQ (QT3 Designer) que hemos venido utilizando hasta el momento. QT4 Designer es mucho más completo e intuitivo que su predecesor, y tiene la potencia necesaria para ser el editor de informes que estábamos esperando.

El procedimiento es:

1. Se crea un infome en el formato nativo de QT4 Designer, al que daremos la extension ar (AbanQ Report). Este fichero se guarda en el directorio reports del módulo correspondiente, tal como se viene haciendo con los .kut

2. Se carga el módulo de informes. AbanQ detecta que hay un fichero .ar nuevo o modificado, ya hace una conversión al vuelo del fichero .ar en .kut

Internamente AbanQ sigue usando el formato kut, pero de cara al usuario o programador, sólo se ha de tocar el .ar desde el editor gráfico.

Desde el editor de QT4 vamos a crear los campos y etiquetas del informe, y los vamos a agrupar en sus niveles correspondientes (encabezados, detalles y pies). Desde el panel de propiedades del editor establecemos:

  • Todas las propiedades de presentación del informe (posición, tamaños, colores, alineación, bordes, tipografía…)
  • Propiedades definidas en AbanQ (campo que se mostrará, decimales, formato de fecha, nivel de encabezados y detalles…)
  • Elementos gráficos: líneas o marcos y definición de su color y grosor, y bordes de campos y etiquetas.
  • Propiedades generales del informe (márgenes, formato y horientación de la hoja)

Veámoslo en alguno pantallazos:

Un informe en el editor QT4
El editor. Vemos un informe de pedido de cliente en QT4 Designer. Las alturas de los niveles y detalles son las que tendrá el informe final. Usamos un fondo anaranjado para distinguir los niveles y la posición de las etiquetas y campos. Vemos a la derecha el panel de propiedades.

Un informe en el editor QT4
El informe en edición. El informe más de cerca. En los campos podemos poner textos de muestra para hacernos una idea del resultado final y establecer la apariencia con más facilidad.

Un informe en el editor QT4
Propiedades de un campo. En el panel propiedades además de las propiedades gráficas del elemento, indicamos qué campo vamos a mostrar y su formato. En este caso es una fecha.

Un informe en el editor QT4
El informe en AbanQ. Vemos la apariencia resultante, casi calcada de la que hemos creado en el editor.

Es necesario resaltar que los informes actuales en formato .kut no se pueden convertir al formato .ar, es necesario rehacer todos los informes actuales para adecuarlos al nuevo formato.

Publicaremos un documento de uso del editor más detallado en su momento.

2/26/2009

Sistema de detección temprana de bloqueos

— Fede @ 5:42 pm

En la versión 2.3 tenemos disponible un sistema experimental, sólo disponible para bases de datos PostgreSQL, que permite detectar bloqueos antes que se produzca, o de forma heurística estimar los posibles riesgos de bloqueo que pueden existir en un momento dado.

El sistema avisa al usuario cuando se encuentra en una situación que puede derivar en un bloqueo o en un bloqueo potencial, permitiendo a este poder esperar o cancelar la transacción en curso y evitar así congelar la interfaz de usuario mientras exista el bloqueo.

Por ejemplo, si dos usuarios están haciendo un albarán, y los dos intentan reservar un mismo artículo en un mismo almacén, se produce una situación de exclusión mutua sobre la cantidad de stock. Hasta ahora se producía un bloqueo que congelaba la aplicación de uno de los usuarios hasta que el otro acabara el albarán, pero con este nuevo sistema uno de los usuarios (el último en llegar ) será avisado de que si continua e intenta reservar stock en ese momento para ese artículo incurrirá en una situación de bloqueo, permitíendole así esperar, cancelar o si quiere definitivamente caer en el bloqueo.

El sistema antibloqueos se puede controlar desde los scripts utilizando los nuevos métodos de la clase FLApplicationInteface y cuya documentación se puede encontrar en el fichero FLObjectFactory.h del código fuente de AbanQ.

Generalmente la forma más sencilla de utilizar este sistema es cuando se llama al método commitBuffer de la clase FLSqlCursor. A partir de ahora este método se puede llamar con un parámetro booleano que indica que se realize una comprobación de bloqueos si es cierto ( true ):


var cursor = new FLSqlCursor( “albaranaescli” );

cursor.setModeAccess( cursor.Insert );
cursor.refreshBuffer();
…..
…..
cursor.commitBuffer( true ); // Con ‘true’ indicamos que se comprueben bloqueos antes de aceptar cambios

2/17/2009

Control de acceso sensible al contexto

— Fede @ 8:10 pm

En AbanQ v3 se han hecho muchas mejoras en seguridad y en el control de acceso, una de estas mejoras se puede probar en los últimas publicaciones de la versión 2.3; Control de acceso sensible al contexto.

La mayoría de los sistemas de control de acceso son estáticos e invariantes con los datos, es decir insensibles al contexto, esto significa que nosotros definiremos reglas del tipo “El usuario Eladio no puede modificar los clientes y no puede ver las cantidades totales de las facturas”. Esta regla se aplica de forma sistemática para todos los clientes y para todas la facturas.

Pero en muchos casos esas reglas de control de acceso necesitan ser aplicadas según el valor de ciertos datos, es decir queremos que sean sensibles al contexto, de tal manera que podamos definir reglas del tipo “El usuario Eladio no puede modificar los clientes de Albacete, y puede ver las cantidades totales de las facturas excepto las que corresponden a los tres meses anteriores”.

Bien pues este tipo de reglas de control de acceso sensibles al contexto ya es posible usarlas en AbanQ, aún de forma limitada en la versión 2.3 y con toda su potencia en la nueva versión.

Ahora cada FLSqlCursor tiene su control de acceso para tablas ( FLAccessControlTable ) que aplica al evaluar una condición cuando se carga un nuevo registro. Este control de acceso se puede definir mediante los scripts, las funciones que podemos usar son estas:


/**
Establece el acceso global para la tabla, ver FLSqlCursor::setAcosCondition().

Este será el permiso a aplicar a todos los campos por defecto

@param ac Permiso global; p.e.: “r-", “-w”
*/
void setAcTable( const QString & ac ) ;


/**
Establece la lista de control de acceso (ACOs) para los campos de la tabla, , ver FLSqlCursor::setAcosCondition().

Esta lista de textos deberá tener en sus componentes de orden par los nombres de los campos,
y en los componentes de orden impar el permiso a aplicar a ese campo,
p.e.: “nombre", “r-", “descripcion", “–", “telefono", “rw",…

Los permisos definidos aqui sobreescriben al global.

@param acos Lista de cadenas de texto con los nombre de campos y permisos.
*/
void setAcosTable( const QStringList & acos );


/**
Establece la condicion que se debe cumplir para aplicar el control de acceso.

Para cada registro se evalua esta condicion y si se cumple, aplica la regla
de control de acceso establecida con FLSqlCursor::setAcTable y FLSqlCursor::setAcosTable.

Ejemplos:

setAcosCondition( “nombre", VALUE, “pepe” ); // valueBuffer( “nombre” ) == “pepe”
setAcosCondition( “nombre", REGEXP, “pe*” ); // QRegExp( “pe*” ).exactMatch( valueBuffer( “nombre” ).toString() )
setAcosCondition( “sys.checkAcos", FUNCTION, true ); // call( “sys.checkAcos” ) == true

@param cond Tipo de evaluacion;
VALUE compara con un valor fijo
REGEXP compara con una expresion regular
FUNCTION compara con el valor devuelto por una funcion de script

@param condName Si es vacio no se evalua la condicion y la regla no se aplica nunca.
Para VALUE y REGEXP nombre de un campo.
Para FUNCTION nombre de una funcion de script. A la función se le pasa como
argumento el objeto cursor.

@param condVal Valor que hace que la condicion sea cierta
*/
void setAcosCondition( const QString & condName, int cond, const QVariant & condVal );


Con estas tres funciones podemos definir cualquier regla de control de acceso a nivel de tabla y que tengan en cuenta el valor de los datos de cada uno de los registros. Se puede establecer un permiso global para la tabla y luego permisos concretos para campos que sobreescriben el global. Por ejemplo este código en masterfacturascli.qs, permite editar el nombre y oculta el cif para registros bloqueados ( campo editable = false ).


function interna_init()
{
var cur = this.cursor();

// Permisos concretos para campos
var acos = new Array( “nombrecliente", “rw", “cifnif", “–” );

cur.setAcTable( “r-” ); // Permiso global sólo lectura
cur.setAcosTable( acos ); // Lista permisos de campos

// La condicion para aplicar la regla es que el campo editable tenga el
// valor false
cur.setAcosCondition( “editable", cur.Value, false );
…….
……
}

Básicamente la definición de reglas sensibles al contexto se reduce en dar un permiso global, permisos concretos de campos y una condición que puede ser, comparar con un valor, con una expresión regular o el resultado que devuelve una funcion de script indicada, a esta función se le pasa el cursor, el contexto, actual de datos que condicionará el que se aplique o no una regla.

2/14/2009

Estilos SVG en informes de AbanQ

— Fede @ 8:36 pm

A partir del Build 14641 de la versión 2.3 vamos ir incluyendo algunas tecnologías extraídas de AbanQ V3 para que sean probadas a modo de prelanzamiento. Intentaremos ir poniendo en el blog algunas entradas comentando las más importantes.

Y como el movimiento se demuestra andando empezamos ya mismo viendo una de esas funciones, Estilos SVG en informes, una pequeña pieza sacada de AbanQ V3 pero muy interesante y que seguro que será de mucha ayuda para mucha gente.

EL CONCEPTO

La idea es simplificar el diseño de informes utilizando estilos SVG fácilmente editables mediante herramientas existentes de diseño vectorial, aprovechando que los informes se pueden guardar en este formato y que ya tenemos un motor que puede interpretar y aplicar los atributos de ficheros SVG en el momento de la presentación.

EJEMPLO BÁSICO

Vamos a modificar el formato de la factura de cliente utilizando esta técnica, utilizando una versión del motor a partir del Build 14641 y la conocida herramienta Inkscape incluida en la mayoría de las distribuciones de Linux.

Guardamos una factura cualquiera en formato SVG, para esto sólo debemos realizar la acción de imprimir y en el visor de informes pulsar el botón “Guarda como estilo SVG” de la barra de herramientas:


El fichero SVG guardado lo editamos con Inkscape y hacemos una pocas modificaciones:



Si volvemos al visor de informes y en el cuadro “Estilo” indicamos el fichero modificado obtenemos la nueva presentación del informe:



Para hacer que este estilo fuera el predeterminado del informe bastaría modificar el fichero .kut e incluir la propiedad StyleName en la etiqueta raiz KugarTemplate:


… kugartemplate BottomMargin=’50′ LeftMargin=’30′ PageOrientation=’0′ PageSize=’0′ RightMargin=’30′
StyleName=’file:/home/falbujer/SVG/prueba.svg’ TopMargin=’50′ …

Si la ruta empieza por file: se buscará el fichero en el sistema de ficheros de disco, si empieza por abanq: el fichero se buscará en la base de datos ( tabla flfiles ). En la base de datos se puede guardar un fichero en Administración, nuevo fichero y copiando y pegando el contenido XML del mismo. También existe el método FLReportViewer::setStyleName para establecer el estilo de un informe desde los scripts de forma dinámica.


EJEMPLO MENOS BÁSICO

En la mayoría de los casos es aconsejable que todo lo que no sean datos que vienen de la consulta que genera el informe sea “dibujado” en el estilo SVG, en vez de hacerlo editando el fichero .kut.

Por eso cuando se utiliza esta técnica las etiquetas Label y Line del .kut deberían de dejar de usarse delegando el dibujo de esos objetos al estilo y al momento final de la presentación, reduciendo así drásticamente el tiempo necesario para diseñar un informe. Para esto podemos “Guardar SVG simplificado”, que sólo contiene los elementos del .kut que provienen de la consulta, es decir los campos de datos:

Continua… (more…)

9/25/2008

¿Qué pasa con AbanQ v3?

— Fede @ 4:10 pm

Mucha gente nos hace esta pregunta y siempre contestamos lo mismo, ya está listo lo que inicialmente teníamos previsto desarrollar, pero aún no lo vamos a liberar. Pero ¿por qué?, ¿sois unos desalmados que nos quereis hacer sufrir? ¿habeis abandonado el proyecto? ¿formais parte de una alianza conspiranoica mundial para nunca sacar el software en su fecha?.

Pues no, la explicación es simple; Un día cuando ya teniamos nuestro AbanQ v3 listo, alguien dijo “bueno pues ya que estamos ¿por qué no hacemos una versión con interfaz Web totalmente compatible con la versión de escritorio?", y así empezó todo. Tenemos esto:

AbanQ GUI V3 para Escritorio

y ahora ya estamos consiguiendo tener además esto:

AbanQ GUI V3 para Web

Continua… (more…)

12/20/2007

Colaboración: Asientos predefinidos

— Antonio @ 7:41 am

Nuestro colaborador Guillermo Molleda, de la Universidad de Sevilla, está ultimando unas mejoras sustanciales en el apartado de Asientos Predefinidos del módulo de contabilidad. Estas mejoras estarán listas en la próxima versión 2.3

Entre estas mejoras está un tratamiento más claro y eficiente de las variables en memoria, así como algunas modificaciones en la interfaz de usuario.

Damos las gracias también a Mathias Behrle por su colaboración con Guillermo a la hora de testear su desarrollo. Danke Mathias!

Plantilla de partidas

11/23/2007

AbanQ v3 : El motor de scripts, parte I

— Fede @ 12:31 pm

Hasta la versión 2 hemos venido usando el magnífico producto de Trolltech, QSA. La verdad es que ha funcionado muy bien y se ha portado como un campeón, pero a la hora de desarrollar AbanQ v3 y ver con detenimiento que podríamos mejorar, hemos visto algunas carencias del motor de script que queríamos solventar, así que hemos desarrollado un QSA con asteroides que trae algunas mejoras, veámoslas.

Más rápido y Ahorra memoria = Menos cansino

QSA incorpora su intérprete de ECMAScript (parecido a JavaScript ), no vamos a entrar en detalle de cómo funciona un intérprete, para el caso nos basta saber que existen una serie de reglas gramaticales que se aplican a un código fuente y que mediante reducciones se van creando los nodos de la gramática que almacenan la información necesaria para ejecutar ese código.

La mayoría de la información que almacenan los nodos de la gramática son cadenas de texto, generalmente correspondientes a literales que se asignan a identificadores de variables, funciones, constantes, etc. Es fácil de prever que el número de cadenas de texto que puede llegar a contener un código medianamente grande es significativo y que una manera eficiente de crearlas y almacenarlas determinará la velocidad de ejecución y consumo de memoria. ¿ Cómo hace esto QSA ?, pues vamos a ver:

Si nos fijamos por ejemplo en una regla de reducción de la declaración de una función:

FunctionDeclaration:
FUNCTION IDENT ‘(’ ‘)’ ResultSignature FunctionBody
{ $$ = new QSFuncDeclNode($2, 0L, $5, $6); delete $2; }

IDENT, es efectivamente una cadena de texto ( el nombre de la función que elige el programador ), que se crea en el analizador léxico con este código:

case Identifier:
if ( (token = QSLookup::find( &mainTable, buffer16, pos16 )) < 0 ) {
qsyylval.ustr = new QString( buffer16, pos16 );
return IDENT;
}

Es decir se hace un new QString( buffer16, pos16 ) cada vez que se encuentra un identificador, ese puntero se pasa al nodo y se elimina; new QSFuncDeclNode($2, 0L, $5, $6); delete $2; ( el $2 hace referencia al parámetro 2 de la regla, es decir a IDENT ). Al crear el objeto nodo, este hace copia de la cadena y la almacena como un atributo suyo. Sólo hemos visto el nodo tipo función, pero es similar para muchos otros nodos que reducen identificadores; variables, vectores, constantes, clases, etc.. Por lo tanto resumiendo, cada vez que el intérprete encuentra un identificador, realiza estos pasos:

  • Crear una cadena de texto con new QString en la cabecera de la memoria
  • Pasarle el puntero de esa cadena al nodo que debe almacenarla
  • El nodo hace copia (profunda) de la cadena
  • Cuando el nodo ya ha copiado la cadena de texto, esta se elimina de memoria

Podemos ver varios inconvenientes en esta manera de actuar, el que más llama la atención es el hecho de repetir sin cesar new’s seguidos de delete’s. Esto es muy ineficiente tanto en consumo de memoria (en el siguiente apartado se habla sobre otros inconvenientes que tiene esta manera de actuar con la memoria) como en velocidad de ejecución, sobre todo teniendo en cuenta que hay muchos identificadores que son literales exactamente iguales en distintas partes del código y es una pena que no nos acordemos de los creados con anterioridad, y así no tener que volver a crearlos, hacer copia y después destruirlos.

En el caso del código de AbanQ, es especialmente interesante acordarse de los literales de los identificadores ya que debido a su estructura jerárquica y predefinida se reusan constantemente los nombres, por ejemplo ¿cuantos identificadores del tipo “internat_init”, “oficial_beforeCommit..”, “bufferChanged”, etc.. hay en los scripts de AbanQ?, efectivamente, un mogollón.

Pues pensando, pensando, si tuviéramos algún contenedor donde almacenar las cadenas de texto de los identificadores, y cada una de ellas etiquetada con una clave unívoca, podríamos reutilizarlas ¿no?. Pero además si esa clave unívoca es un número, se la puedo pasar a los nodos que ya no tendrán que copiar la cadena, sólo almacenar esa clave y cuando se vaya a usar realmente la cadena de texto hacer una búsqueda por clave en el contenedor.

Con esto conseguimos:

  • Ahorrar memoria ya que las cadenas repetidas sólo se almacenan una vez en el contenedor y los nodos sólo deben almacenar los números clave que hacen referencia a ellas.
  • Rapidez de ejecución ya que sólo creamos las cadenas nuevas y no se realizan copias profundas de las mismas en los nodos. Estas copias profundas son lentas, mucho más que el hecho de almacenar simplemente un número.

Bien pues ahora sólo queda elegir que tipo de contenedor usamos y cómo generamos esas claves unívocas.

Como contenedor nuestro planteamiento está pidiendo a gritos una tabla Hash ( QHash ) que almacena pares (Clave, Valor), este tipo de contenedor permite realizar búsquedas muy rápidas y optimiza bastante bien la memoria, el contenedor elegido es QHash(quint32,QString) , o lo que es lo mismo claves tipo entero sin signo de 32 bits que identifican a cadenas de texto.

Para crear las claves unívocas lo ideal sería tener una función inyectiva, o uno a uno, que tomando como entrada una cadena de texto devolviera un numero de 32 bits único para ella. Bien, pues esto que parece tan fácil tiene tela si queremos que esa función sea lo suficientemente rápida cómo para que pase desapercibida. Realmente lo que estamos buscando es una función hash perfecta que garantice que no existan colisiones ( en este caso, una colisión se produce cuando para dos cadenas distintas se genera el mismo número de 32 bits ). La buena noticia es que la funciones hash perfectas existen, la mala es que son muy lentas. También tenemos la opción de usar una función hash no perfecta y asumir un mínimo riesgo de colisión. Calculando ese riesgo vemos que es perfectamente asumible con ciertas funciones hash rápidas y no perfectas, por lo que finalmente hemos decidido que merece la pena usar esta opción. La función elegida es esta:

uint QSLexer::hashUstr( const QString & s )
{
int len = s.length();
if ( !len )
return 0;
uint hash = 0;
for ( int i = 0; i < len; ++i ) {
hash += s[ i ].unicode();
hash += ( hash << 10 );
hash ^= ( hash >> 6 );
}
hash += ( hash < < 3 );
hash ^= ( hash >> 11 );
hash += ( hash < < 15 );
return hash;
}

Esta función es muy rápida y la probabilidad media de colisión es de 1 entre 4.294.967.296 ( 2 elevado a 32 ), aunque realmente esa probabilidad de colisión es aún menor, ya que en la practica se maneja un diccionario bastante reducido de palabras. En resumidas cuentas casi podríamos decir que es más fácil que te toque la lotería del niño que tener una colisión de estas.

Lo que hemos hecho al final es modificar QSA para tener una tabla Hash global a todos los nodos y generar claves para las cadenas de texto de los identificadores que van pasando por el analizador léxico. De esta forma los pasos que realiza el intérprete cuando encuentra un identificador son estos:

  • Calcula la clave unívoca de la cadena de texto mediante nuestra función hash.
  • Si la clave ya existe en la tabla Hash global no hace nada, de lo contrario la almacena en esta tabla.
  • Le pasa esta clave numérica al nodo que debe almacenarla

El primer paso es muy rápido, y en el segundo para muchos casos sólo se realizará una búsqueda en la tabla, ya que hay muchas probabilidades de que la clave ya exista. El tercero también es muy rápido ya que sólo consiste en almacenar un valor numérico. Parece que hemos ganado algo, en el último apartado veremos si es verdad, ahora veamos lo que dejamos pendiente sobre otros problemas que tenía QSA con la memoria.

Fragmentos de mi memoria

Otro problema que solventa la nueva gestión de las cadenas de texto que acabamos de describir, merece mención especial. El problema es la fragmentación de la cabecera de memoria, también conocida como heap o memoria dinámica. En la implementación original de QSA hemos visto que se repiten hasta la saciedad la creación ( new’s ) y destrucción ( delete’s ) de cadenas de texto, tantas veces como identificadores encuentra el analizador léxico.

Ya sabemos que un new reserva memoria y un delete la libera, en este caso las reservas de memoria en general son excesivamente pequeñas al referenciar en la mayoría de los casos a cadenas de texto cortas, unos pocos bytes. Estos trozos pequeños de memoria se crean en el heap de forma dinámica conforme se demandan y no de forma contigua, generalmente intercalados con otros trozos mas grandes que forzosamente se crean durante la ejecución, al liberarlos se marca como libre el trozo que ocupaban, por lo que al final tenemos muchos trozos pequeños libres dispersados por el heap. Tal y como lo hace la implementación original de QSA al realizar un análisis léxico de mucho código deja plagado el heap de mini-trozos no contiguos de memoria libre, en AbanQ se analiza muchísimo código constantemente por lo que en nuestro caso el problema aún es mas grave si cabe.

El segmento heap aumenta su tamaño cuando se pide reservar un nuevo trozo de memoria que no cabe en un trozo liberado. Siempre que se pueda reubicar una reserva de memoria en un trozo de memoria liberado el heap no crecerá, ya que reusa memoria liberada. Cuando tenemos muchos trozos pequeños no contiguos, que en suma son mucha memoria libre pero que por separado son difíciles de reusar al no poder albergar nuevas reservas de memoria mayores, estamos ante un problema de fragmentación. Al crear trozos tan pequeños se obliga a crecer mucho al segmento heap ya que en la práctica aunque esos trozos están libres es como si estuvieran ocupados al no poder reusarse. Como la memoria no es infinita podemos llegar aun desbordamiento y hacer caer a la aplicación cuando en realidad no se necesita tanta memoria.

En los sistemas Unix se soporta mejor este crecimiento de la memoria dinámica y rara vez se produce un desbordamiento, pero los sistemas Windows lo llevan peor, esta es una de la razones por la que Windows da calabazas cuando AbanQ le pide marcha.

En la nueva implementación esto queda resuelto ya que todas las cadenas se crean una sola vez y se almacenan en una tabla hash que internamente compacta y agrupa sus elementos en memoria contigua, es decir, se usa mucha menos memoria y una vez que se libera es reutilizable.

La prueba del algodón

Ahora tenemos que ver si realmente todo esto ha servido para algo o no. La única manera que se me ocurre es ejecutar código y medir tiempos, tampoco vamos a ser muy exigentes, un par de scripts típicos, no sea que al final nos salgan resultados negativos y nos deprimamos.

Probamos con Fibonacci:

function fibonacci(n) {
if (n == undefined)
throw “Try calling the main function…";
if (n == 0)
return 0;
else if (n == 1)
return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
function oficial_fibo( n:Number ):String
{
var d1 = new Date();
var fib;
for (var x = 0; x < = n; ++x) {
fib = fibonacci(x);
print(’Fibonacci number: ‘ + x + ‘, is: ‘ + fib);
}
var d2 = new Date();
var e = d2.getTime() - d1.getTime();
print( ‘Total time : ‘ + e + ‘ms’ );
}



fibo( 22 ) - 22 términos

QSA viejo

QSA nuevo

ejecución 1

4725ms

3456ms

ejecución 2

4687ms

3511ms

ejecución 3

4737ms

3456ms

No está mal

Ahora con un script genérico con consulta SQL:

function prueba()
{
var d1 = new Date();
var res:String = “Version ” + this.version();
var cur:AQSqlCursor = new AQSqlCursor( “divisas” );
cur.select();
while( cur.next() )
res += “n
” + cur.valueBuffer( “descripcion” );
var qry:AQSqlQuery = new AQSqlQuery();
qry.setTablesList( “clientes” );
qry.setSelect( “nombre” );
qry.setFrom( “clientes” );
if ( qry.exec() )
while( qry.next() )
res += “n
” + qry.value( 0 );
var bancos;
bancos = [["0030″, “BANESTO"],["0112″, “BANCO URQUIJO"],
["2085″, “IBERCAJA"],["0093″, “BANCO DE VALENCIA"],
["2059″, “CAIXA SABADELL"],["2073″, “CAIXA TARRAGONA"],
["2038″, “CAJA MADRID"],["2091″, “CAIXA GALICIA"],
["0019″, “DEUTSCHE BANK"],["0081″, “BANCO DE SABADELL"],
["0049″, “BANCO SANTANDER CENTRAL HISPANO"],["0072″, “BANCO PASTOR"],
["0075″, “BANCO POPULAR"],["0182″,"BANCO BILBAO VIZCAYA ARGENTARIA"],
["0128″, “BANKINTER"],["2090″, “C.A.M."],["2100″, “LA CAIXA"],
["2077″, “BANCAJA"],["0008″, “BANCO ATLANTICO"],
["0061″, “BANCA MARCH"],["0065″, “BARCLAYS BANK"],
["0073″, “PATAGON INTERNET BANK"],["0103″, “BANCO ZARAGOZANO"],
["2013″, “CAIXA CATALUNYA"],["2043″,"CAJA MURCIA"],
["2103″, “UNICAJA"],["2105″, “CAJA DE CASTILLA LA MANCHA"],
["0042″, “BANCO GUIPUZCOANO"],["0138″, “BANKOA"],
["3056″, “CAJA RURAL DE ALBACETE"]];
for (var i:Number = 0; i < bancos.length; i++)
res += “
” + bancos[i][0] + ” ” + bancos[i][1];
var d2 = new Date();
var e = d2.getTime() - d1.getTime();
print( ‘Total time : ‘ + e + ‘ms’ );
return res;
}


QSA viejo (tiempo/memoria)

QSA nuevo (tiempo/memoria)

ejecución 1

16ms / 51.4 Mb

38ms / 8.7 Mb

ejecución 2

12ms / 51.4 Mb

6ms / 8.7 Mb

ejecución 3

13ms / 51.6 Mb

6ms / 8.8 Mb

La primera vez es mas lento porque carga la tabla hash, luego es el doble de rápido. Con la memoria si que se nota de verdad.

Al parecer si que hemos conseguido algo, pero aún se puede conseguir más, ya lo veremos más adelante.

11/20/2007

AbanQ v3 llama a las puertas de InfoSiAL

— Fede @ 7:40 pm

Pues sí, la versión 3 del motor de AbanQ está a punto de ver la luz después de varios meses de desarrollo. Hay avances muy significativos que recogen toda la experiencia que hemos adquirido durante estos años con AbanQ y del trabajo diario con nuestros clientes y usuarios. Estamos ante una pieza de software realmente avanzada y sofisticada que seguro gustará a los desarrolladores y usuarios.

En esta entrada voy a resumir lo más interesante que traerá esta nueva evolución del motor, aunque mi intención es ir añadiendo nuevas entradas con explicaciones más detalladas sobre los detalles técnicos de los distintos subsistemas que componen el motor, así que si te interesa todo el galimatías técnico pásate por aquí de vez en cuando.

AbanQ V3

¿Que hay de nuevo?

- Totalmente reescrito en Qt4. Entre otras cosas esto significa mejor funcionamiento en todas las plataformas, incluida Windows.
- Ya que lo hemos reescrito pues hemos mejorado la arquitectura creando distinto módulos de lo que antes era la librería flbase; AQCore, AQSql, AQNetwork, AQScript, etc..
- Sistema de importación automática de módulos de la versión 2, totalmente transparente para el usuario. Pueden convivir perfectamente motores de la version 2 con los de la versión 3.
- Posiblidad de conectar simultáneamente a varias bases de datos desde una misma instancia de aplicación.
- Interfaz mejorada con formularios flotantes ( docks ), navegación en árbol con marcadores y recientes.
- Diseño totalmente MVC, separando completament la lógica de la presentación. Hojas de estilos.
- Sistema propio de ficheros basado en SQL ( AQSqlFileSystem )
- Cada módulos ofrece una interfaz tipo shell (AQShell )
- Consola de sistema para manejar el sistema de fichero SQL y con interfaz para manejar los módulos mediante comandos.
- Drivers mas eficientes para MySQL y PosgreSQL
- Nuevo motor de scripts, basado en QSA y WebKit
- Compilación de scripts en bytecode. Interpretación rápida de bytecode

AbanQ V3

AbanQ V3

6/26/2007

Open Document como motor de informes alternativo

— site admin @ 1:03 pm

Hace poco publicamos una nueva extensión que permite generar un presupuesto con formato de Open Document (odt) a partir de una plantilla de referencia también en odt. La extensión crea el documento a partir de una serie de parámetros y de las propias líneas del presupuesto.

A raíz de esto hemos estado investigando la posibilidad de utilizar Open Document como un sistema de generación de informes alternativo de forma genérica. Por lo pronto estamos preparando una pequeña extensión que permitirá definir formatos de factura en odt.

Ejemplo de documento odt

La principal ventaja de esto es que el usuario puede definir el formato de sus informes de modo totalmente libre mediante Open Office, NeoOffice, etc, ya que en Open Document el estilo y los datos están separados.

El problema reside en que Kugar, a través de numerosas adaptaciones, nos permite realizar bastantes cosas que con odt habría que reprogramar: campos calculados, varios niveles de detalles, suma y sigue, etc.

El cualquier caso para informes sencillos vemos que es una alternativa muy interesante.

2/13/2007

Estreno del Blog

— site admin @ 12:33 pm

Los programadores de InfoSiAL estrenamos este blog en el que iremos publicando nuestras ideas y proyectos a medida que se vayan desarrollando.

InfoSiAL

Powered by WordPress

Categorías
Histórico
September 2010
S M T W T F S
« Jun    
 1234
567891011
12131415161718
19202122232425
2627282930  
Buscar