Ordenando arrays

Algunas veces es necesario trabajar con arrays ordenados de mayor a menor o viceversa. Esto se suele hacer usando locate para controlar la entrada de los datos en el array de forma ordenada; pero se pude dar el caso de que hagamos una carga secuencial y luego queramos que todo se ordene. Aquí es donde opera la magia.

En el caso de hacerlo con locate podremos usar este código entendiendo que la variable namesite no se repite y es por donde queremos ordenar

locate(namesite,myarray,1;index1;’AL’) then
* existe namesite, y podemos actualizar o sumar o lo que sea en otros atributos como por ejemplo
myarray<2,index1>+=ocupag
end else
* no existe namesite y tenemos la posicion, insertamos
myarray=insert(myarray,1,index1;namesite)
myarray=insert(myarray,2,index1;ocupag)
end

La alternativa es que hayamos cargado todo en secuencial y al final optamos por colocarlo usando la función u1072.

Para ello vamos cargan nuestro array de forma secuencial con un simple myarray<-1>=’valor’ o valores y al terminar procesamos la función :

myarray=oconv(myarray,’u1072′);* Orden Ascendente

Y el contenido de myarray estará colocado en orden ascendente. No es posible a la inversa pero siempre se puede recorrer el array de atras adelante para obtener ese efecto.

Sustituyendo cadenas de caracteres en D3

Hay veces que necesitamos cambiar algún contenido de una cadena de caracteres por otro y esto en D3 se hace fácil, pero hay que acordarse; por es lo escribo aquí

Por un lado, cambiar un solo carácter, se hace directamente con la función convert

convert ‘caracter1’ to ‘caracter2’ in string

Pero el problema esta cuando queremos una varios caracteres , no solo uno.

Aquí podemos usar el bucle de búsqueda como el siguiente :

  • loop
  • aa=index(string,’grupodecaracteres’,1)
  • while aa do
  • string[aa,lendelgrupodecaracteres]=nuevoscaracteres
  • repeat

Ya, la forma más técnica usando las funciones que nos proporciona d3, seria llamando a la u009e de forma que haga el reemplazo del tirón , sin bucle

string=oconv(«u»:att:’quecambiamos’:att:’queponemos’:att:string,’u009e’)

A vueltas con DKIM

A vueltas con el DKIM, es un texto que dejo para seguir los pasos que voy dando y las explicaciones oportunas sobre porque falla y como lo resuelvo, si es que lo logro.

El escenario es un servidor donde hay otros dominios que SI resuelven bien DKIM, y tan solo uno de ellos se está negando a resolver la firma. De hecho voy a probar otro dominio por si la casualidad existe, no sea que realmente fallan todos, excepto uno.

Al tratarse del mismo servidor, mismo sendmail y misma configuración DNS, la cosa se complica. He generado de nuevo el DKIM pero no es eso, tras esperar unas horas a que se replique de forma correcta, sigue fallando.

Hago las pruebas de validez, enviando email a https://dkimvalidator.com y puedo comprobar si recibe correctamente la firma DKIM

Retrieved this publickey from DNS: v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpeeqnCTHsa1mYhOfKM1uXNtzY4Yu7aSRa0bOkce8inBHr0xGpnyz26p2ax9Gwh7afSclFrc+o84W1o+no/vzAznEAxXEJs39CwXtfa/YQXMnIZPrhl+xYFTbC+hzjSRfexLu/+wfawnjyQG94iRz3X7+tlG5Ij7T8Sz4moM4FVwIDAQAB

Y es correcta, la misma que tengo en el DNS tras esperar un tiempo de replicación, de unas 2 horas máximo.

Validating Signature 
result = fail
Details: bad RSA signature

Y sin embargo esta generada de nuevo limpiamente. He probado con otro dominio, del mismo servidor y el resultado es pass ; osea que el problema, es solo en este, que raro suena. Pensé que podía faltar su entrada en el archivo keylist, pero no, estaba ahí.

Con palo de ciego veo que el SPF tiene declarada una ipv4 mal, es decir, un numero erróneo, lo corrijo con esperanza de que suene la flauta porque realmente digo que poco tendrá que ver el SPF de una IP mala que ademas no es la que esta enviando.

Una prueba nueva, sencilla de hacer, intercambio los datos de dos dominios, uno que funciona y el que falla, de forma que sustituyo en ambos las claves publicas y privadas en el directorio dkim-milter ademas de cambiar las publicas del DNS. Con esto veremos que pasa en ambos dominios. Se intercambian las situaciones ?

Pues no, lamentablemente, fallan los dos dominios. Vamos a ver si reponiendo la situación se vuelven a poner las cosas, al menos, como antes. De momento parece que el error esta en las KEYS generadas nuevas. Si repongo la antigua y funciona, será que el nuevo generador de claves es erróneo y habrá que anailizar el tipo de clave vs confgiuración del dkim que no cuadra bien.

De Locos, me quedo en blanco y resulta que solo tuve que relanzar el demonio dkim-milter para que todo se solucionara; eso si, previo quitar las lineas duplicadas y hasta triplicadas que había en el archivo keylist; que de hay venia el error.

Convirtiendo juegos de caracteres

Mejorando nuestro producto prod3erp que conecta directamente la base de datos pick d3 con el apache linux (si alguno esta interesado se comercializa).

Pues bien, al transmitir datos con caracteres especiales, se producen varios probleas. Si el dato entra desde la web (en UTF8 o en ISO8859) el Pick D3 no lo reconoce correctamente y muestra en la consola o los programas que se ejecuten caracteres extraños; y a la inversa, si los datos se introducen con el teclado en la consola Pick, tenemos una correcta visualización en los programas internos pero unos caracteres extraños cuando se transmiten al Apache y se muestran en webs UTF 8 o ISO8859.

Después de dar muchas vueltas, decidó que lo mejor es estandarizar ambos juegos de caracteres y buscar un protocolo en medio que los convierta sin necesidad de tener que preocuparme por ello. Para estar todo correcto doy por supuesto que la web va a trabajar en UTF-8 y la base de datos D3 Pick en codigo CP850.

En el sistema prod3erp incluyo entonces un protocolo que convierte todo lo que entra en UTF-8 o ISO8859 a codigo CP850 y otro protocolo en salida que convierte de CP850 a UTF-8.

Problema resuelto.

Para hacerlo me he apoyado en las utilidaddes de linux file e iconv que me indican el tipo de archivo que es y me permietn hacer las conversiones. Esto que a priori podria haber lentificado el proceso es lo suficientemente rápido como para que no se note la velocidad.

A vueltas con el ASCII

Siempre que me topo con una necesidad de conversión de códigos ASCII en D3, me cuesta recordar cual es la función para obtener el código a partir de un carácter. Y esto es porque esa función, al menos yo, se usa mucho menos. En fin, el caso es que un día me prometí escribir todo aquello que me obliga a buscar documentación o investigar cuando estoy tirando código.

En este caso, el tiempo de búsqueda a sido bastante corto, así que el artículo, también será corto.

Al grano. La función para obtener el carácter a partir de un código ascii es CHAR, mientras que la inversa, la que he buscado, es SEQ.

De esta forma, si queremos obtener el código ascii de la ‘A’ será :

SEQ(‘A’)

Lo que respondera con un bonito 65: mientras que si queremos obtener el carácter que corresponde al código ascii 65 será :

CHAR(65)

Que nos devolverá una bonita ‘A’

Y esto es todo de este sencillo post que solo servirá para que yo localice el seq de forma más rápida la próxima vez que lo necesite.

Mezclando listas anidadas con D3 – Uso de READNEXT #2

Como continuación del articulo anterior, puedo añadir una informacion adicional que he tenido que recuperar al encontrarme con un sistema mas antiguo que no soporta el uso del rtnlist en la sentencia execute.

Hay una alternativa, pero solo controlaremos dos listas, una primaria y una secundaria, si bien es cierto que será mas que suficiente en la mayoria de los casos.

La primera lista sera generada con normalidad sin datos adicionales y sera en el segundo select donde añadimos la opción (s que convierte la selección en secundaria. De esta forma podremos usar el readnext con el modificador secondary y no se mezclan los punteros de los respectivos readnext.

Intentare que se vea mas claro con este ejemplo del mismo código del ejemplo anterior adaptado a esta nueva forma de controlar las listas :

execute «lista colores»
loop
readnext color
execute «selecc articulos con color =»:color:» (s»
loop
readnext itemarticulo secondary
….. sentencias con itemarticulo …
until eof do repeat
until eof do repeat

De esa nueva forma también se pueden anidar listas y ejecuciones selecc sin preocuparnos de que se mezclen punteros y por tanto resultados.

Mezclando listas anidadas con D3 – Uso de READNEXT

En ocasiones exigencias del guión obligan a trabajar con listas dentro de listas; esto, provoca que tengamos que controlar muy ben de donde tira nuestro readnext si no queremos sorpresas y errores de logica.

Me explico, supongamos que hacemos un select de un fichero y luego del resultado que recorremos secuencialmente debemos hacer un nuevo select para recorrer secuencialmente otra lista. Que lio no !!!

Pondre un ejemplo mas claro. Imaginar que tenemos que sacar una lista de colores grbada previamente y que de cada color de la lista debemos sacar los articulos que tienen ese color con un selecc de articulos con color =»X» para sacar finalmente un listado de ellos.

Si hacemos este codigo : (pongo solo las lineas afectadas)

execute «lista colores»
loop
readnext color
execute «selecc articulos con color =»:color
loop
readnext itemarticulo
….. sentencias con itemarticulo …
until eof do repeat
until eof do repeat

Tendremos el problema de que se mezclan los readnext de ambas sentencias selecc y no funcionara correctamente, para eso usamos el asignar a una variable una lista de forma que podamos usarla focalizada en el readnext.

Usamos la sentencia rntlist de execute y la cosa quedaria asi, mas o menos :

execute «lista colores» rtnlist lista1
loop
readnext color from lista1
execute «selecc articulos con color =»:color rtnlist lista2
loop
readnext itemarticulo from lista2
….. sentencias con itemarticulo …
until eof do repeat
until eof do repeat

De esa sencilla forma se pueden anidar listas y ejecuciones selecc sin preocuparnos de que se mezclen punteros y por tanto resultados.

Calcular la semana de una fecha

Vimos en otra entrada de este blog todas las conversiones de fechas, pero no exisita una que nos diera la semana del año. Si queremos hacer un informe de estadisticas semanales y nos gustaria poner en la cabecera el numero de la semana, o lo que es mas importante, usar el numero de la semana como itemid de los acumulados, necesitamos conocer este dato.

La necesidad agudiza el ingenio, asi que podemos hacernos con este simple codigo un
calculo de la semana anual a la que corresponde una fecha dada, por ejemplo la del dia en que estamos :

semana=int((date()-iconv(‘31.12.’:oconv(date(),’dy’)-1,’d’))/7)+1
print semana

 

Conversiones de Fechas

Cuando trabajamos con fechas en D3 sabemos que es importante tener en cuenta los formatos interno y externo de las fechas. A veces tenemos que hacer operaciones no habituales y no recordamos como se convertia. Voy a exponer aqui las conversiones que permiten las fechas en D3.

El formato interno es un numero que representa el numero de dias transcurridos desde el 01 de enero de 1968 , y a esa fecha se la conoce como la fecha uno (1).  Este calculo de dias nos lo hace d3 usando las conversiones de formato ‘date’.

hoy=’11/04/2013’print iconv(hoy,’d’)
Dara como resultado : 16538 que es el numero de dias desde 01.01.1968 hasta hoy

Clasificar y ordenar numeros del formato 16538 es mucho mas sencillo que trabajar con fechas en formato , digamos humano, por eso es altamente recomendable trabajar en los archivos con fechas en formato interno.

Pasar del formato interno al externo es donde tenemos multiples posibilidades de conversiones y de obtener datos diferentes. La sintaxis siempre es :

resultado=oconv(fecha_en_formato_interno,’dxx’) donde lo importante aqui es el xx que permite combinaciones interesantes con las siguientes :

Si usamos ‘d’ obtenemos la fecha en formato texto : 13 Apr 2013
d2-  muestra fecha completa separada con guiones y dos digitos para el año : 13.04.13
d4. muestra fecha completa separada por puntos y 4 digitos para el año : 13.04.2013
d/ muestra fecha completa separada con barras y 4 digitos para el año : 13/04/2013
d0 muestra dia y mes en letra sin año : 13 Apr
d0- muestra dia y mes sin año separado por guion : 13-04
dd muestra el dia en numero :13
dm muestra el mes en numero : 04
dma muestra el mes en letra, pero en ingles : april
dq muestra el trimestre en numero : 2
dw muestra el dia de la semana : 6
dwa muestra el dia de la semana en letra, pero en ingles : saturday
dy muestra unicamente el año a 4 digitos : 2013
d2y muestra unicamente el año pero en 2 digitos : 13

Muy completo, verdad, pero falta algo, cual es la semana ? que semana del año es ? Esto no lo da la conversion, pero si unas pocas lineas de programacion que dejo en otra entrada.