DevelUY

Planeta de desarrolladores uruguayos

9 de marzo de 2010

Bruno Buzzi

Influencias: Anécdota de Steve Jobs con Smalltalk

Influencias: Anécdota de Steve Jobs con Smalltalk

Smalltalk fue creado en la Xerox en Palo Alto Research Centre (PARC) entre la década del 70 y principios del 80.

Todo lo desarrollado por la Xerox en aquel entonces ha influenciado de manera muy fuerte todos los aspectos de la informática.

En determinado momento (por el año 1979) Steve Jobs hizo una visita a PARC, el centro de investigación de la Xerox. Un tiempo después comento:

“Y ellos (PARC) me mostraron 3 cosas. Pero había quedado tan segado por la primera que no le preste atención a las otras dos.

Una de las cosas que me mostraron fue la programación orientada a objetos. Ellos me mostraron eso pero ni siquiera le preste atención.

Otra cosa que mostraron fue una red de computadoras… tenian más de 100 computadoras Alto todas conectadas usando Emails, etc, etc.

Tampoco le preste atención a eso. Había quedado tan segado por la primera cosa que me mostraron, que fue la interfaz grafica de usuario (GUI graphical user interface)”

Texto sacado de Triumph of The Nerds (transcript)

Luego Steve Jobs tomaría las ideas de la “primera cosa que le mostraron” (la GUI) en PARC y construiría su exitosa Macintosh.

Lo que vio Steve Jobs fue el Smalltalk-79/80 corriendo en una computadora ALTO, con su GUI, además de procesadores de texto, editores de imágenes y sonido, etc.

La Alto computer fue la visión de Alan Kay y el trabajo por más de una década con un equipo multidisciplinario.

En la siguientes figuras vemos que fue lo que vio (algunas de las fotos son del 1980Steve Jobs en el año 1979 (recordar en el año 1979):

(las fotos pueden encontrarse en: http://www.digibarn.com/collections/software/alto/)



por smalltalkuy, el 9 de marzo de 2010 a las 20:50

Sebastian Gomez (ingles)

New features to the Azure Web Storage Explorer

On the first version you could only manage blobs, upload, delete and download them. Now I added the same functionality for Queues and Tables. I found a pretty cool way of showing unstructured data from the Azure tables from a gridview control. How? with my good old friends the DataSets :) I also updated the source code so you can download the source files from the version that it’s right


por Sebastian (noreply@blogger.com), el 9 de marzo de 2010 a las 19:00

Dario Clavijo

Script para leer Cordenadas del GPS en Android

El siguiente script lo encontre acá y como me gusto decidi hacerle un par de modificaciones mínimas para que nos de mas datos. Y lo resultante lo guarde en un archivo CSV que después lo podemos importar fácilmente en cualquier aplicacion.

import android, string, time
droid = android.Android()
droid.startLocating()
time.sleep(10)
while True:
  l = droid.readLocation()
  outstr = str(l['result']['longitude']) + ',' + str(l['result']['latitude'])  + ',' + str(l['result']['altitude'] + ',' + str(l['result']['speed']) + ',' + str(l['result']['bearing']) + ',' str(time.time())

  if l['result']['provider'] == 'network':
    droidfile = '/sdcard/droidtrack_cell.csv'
  else:
    droidfile = '/sdcard/droidtrack_gps.csv'
  fh = open(droidfile,'a')
  res= fh.write(outstr +'\n' )
  res = fh.close()
  time.sleep(10)

por Daedalus (Daedalus2027@gmail.com), el 9 de marzo de 2010 a las 15:52

Enrique Almeida

Usabilizando Genexus: Order en grillas.

Muchas veces por problemas de performance, es conveniente evitar que los registros vengan ordenados por algún criterio. La diferencia de performance en la base de datos, puede ser muy grande si se elimina la clausula ORDER BY de la sentencia SQL, sobre todo si la misma contiene joins. Hoy en GeneXus se puede programar en los for each, poniéndole order none, con lo cual se puede lograr que la

por noreply@blogger.com (Enrique Almeida), el 9 de marzo de 2010 a las 03:30

8 de marzo de 2010

Marcos Crispino

Versión movil del blog

MoFuse es un sitio que permite crear una versión móvil de cualquier sitio web.

En particular, puede crear una versión móvil de cualquier blog sin ningún esfuerzo, y además lo hace de forma gratuita. Lo único es que agrega publicidad, pero creo que es un precio que vale la pena pagar.

A partir de este momento, este blog puede ser accedido desde cualquier teléfono móvil con acceso a internet desde http://marcoscrispino.mofuse.mobi

Si acceden a esa dirección desde una computadora, muestra una página web con un emulador...

Así es como se ve en el iPhone:

por noreply@blogger.com (Marcos Crispino), el 8 de marzo de 2010 a las 22:07

7 de marzo de 2010

Marcos Crispino

Infinidad de galaxias

Esta imagen es increible, no deja de sorprenderme:


Fue tomada por el Hubble, apuntando hacia una zona aparentemente "vacía" del espacio, una región que ocupa aproximadamente el ancho de 1/15 del ancho de la luna llena.

A ver si logro compartir mi asombro... Se necesitan 30 millones de imágenes como esta para cubrir todo el cielo, y esta imagen fue tomada en una zona del espacio que se consideraba prácticamente vacía!

Pero para que lo voy a explicar yo, si Phil Plait lo explica mucho mejor...

También me gustó este articulo que habla del tema, sobre todo la referencia de Carl Sagan al final sobre "the Pale Blue dot".

Nota: tener en cuenta que "one billion" es 109.

por noreply@blogger.com (Marcos Crispino), el 7 de marzo de 2010 a las 21:20

Francisco Castro

El juego de la vida en Atari BASIC

Para todos mis amigos, una nueva implementación del clásico juego de
la vida:

http://en.wikipedia.org/wiki/Conway's_Game_of_Life

...

por 7 de marzo de 2010 a las 03:36

4 de marzo de 2010

Fernando Briano

@ FING

Facultad de Ingeniería

Facultad de Ingeniería

Retomé las clases en Facultad de Ingeniería, lo que justifica todo lo que no postee en los próximos tiempos :P

Nos vemos ahí, visiten Foro Fing

por fernando, el 4 de marzo de 2010 a las 16:18

Alejandro Segovia

“Me la Complicás” -Todo lo que está mal en Ancel

“Me la Complicás”. De todo lo sucedido hoy, éstas son las tres palabras que hicieron la impresión más fuerte en mi. Las escuche de boca de una funcionara de Ancel en lo que puedo describir como una miserable experiencia como cliente de una empresa Uruguaya de telefonía móvil.

Desde hace días estoy intentando hacer un “agregado” con un plan de datos 3G a mi contrato. Se trata de un procedimiento que implica duplicar el monto mensual que tengo que pagar en mi factura y que uno pensaría que una empresa normal estaría interesada en que yo (y todos sus clientes) adquiriera. Ancel, sin embargo, no es una empresa normal, sino que por el contrario, parece estar empeñada en hacerme las cosas lo más complicadas posible antes de proveerme el servicio, al punto de dudar seriamente si debería continuar siendo cliente de esta compañía.

Esta historia es larga, pero creo que deberías leerla, sobre todo si eres Uruguayo.

Todo comenzó la semana pasada. Quería habilitar un plan 3G en mi celular para poder compartir su conexión a Internet con mi Laptop y poder trabajar desde el interior del país, donde no dispongo de una conexión de banda ancha.

Dado que ya cuento con el equipo y además tengo un contrato a dos años, me comuniqué con mi proveedor para solicitar que se me habilitara el servicio. Después de varios intentos y un tiempo promedio de espera de 5 minutos, logré ser atendido por un ser humano, quien me informaba que lo que yo quería realizar no podía ser hecho por teléfono, ya que tenía que firmar una modificación al contrato.

Entre el fin de semana, el cambio de mando en nuestro país y el hecho de que la autodenominada “Empresa de los Uruguayos” no trabaja después de las 14:00 horas un sábado, tuve que esperar hasta ayer, martes 2 para realizar mi trámite.

Me dirigí a un local comercial de Ancel ubicado en 8 de Octubre y Pernas, retiré un número y miré en la pantalla. Tenía el 58 y se iba atendiendo por el 30… Restaban 28 números para que me atendieran y de los seis puestos de atención al cliente, tan solo dos estaban habilitados. Claramente, con 27 números intermedios, el local se encontraba desbordado de gente.

Tras una hora de espera, fui recibido una señora quien denotaba malas ganas de atenderme. Imaginé que estaría pensando que debía estarla molestando tanta gente en el local, pero creame señora, no es fácil para nosotros tampoco. Procedí a indicarle exactamente lo que quería, a modo de minimizar el tiempo del trámite, pero antes de poder terminar, me respondió que el sistema de ADSL estaba “caído”, por lo cual no se podía realizar mi trámite.

Le dije que mi trámite era con Ancel, y que nada tenía que ver con AntelData. Verás, es que Ancel, AntelData y Antel, son en realidad una sola compañía que a veces atiende a todo su público en los mismos locales. Esto hace que los lugares se llenen de gente, las colas se mezclen y los trámites sean tareas aburridas.

La señora que me estaba atendiendo me contestó que para habilitarme el cambio, tendría que ingresar información en el sistema de ADSL de todos modos, por lo cual mi trámite era imposible y que volviera mañana.

Le dije que había estado haciendo una hora de cola, pero me repitió lo mismo: “no se puede, vuelva mañana”. “Mañana?”, pensé. Pero voy a tener que hacer la cola denuevo… “a qué hora abren”? -”A las nueve”. -”y hay mucha gente a esa hora”, pregunté. -”No sé, porque yo no vengo a esa hora”, sentenció.

Que horarios más extraños hace esta señora, pensé, dado todo esto ocurrió al mediodía. Debe entrar a trabajar a las 10:00 u 11:00. Me fuí, tranquilo, pensando, bueno, ya harán andar el sistema.

Hoy Miércoles volví, saqué número y miré la pantalla. Tenía el 230 e iban atendiendo el 199. Misma historia, solo dos de seis puestos de atención abiertos. Local lleno de gente.

A medida que comenzó a trascurrir la hora que tuve que esperar, y a 40 minutos de la hora de cerrar el local, comenzaron a habilitar más puestos de atención. Claramente los empleados se querían retirar y nadie de ahí se iba a ir hasta que se nos atendiera a todos, por lo cual que comenzaron a apurar.

Desafortunadamente, cuanto más rápido se intenta atender a la gente, peor es la atención brindada. Una regla de la cual los empleados de Ancel no son la excepción. Habiendo desaprovechado todo el día (mientras se armaba cola y más cola) ahora deseaban compensar para irse temprano. Así, te imaginarás, la gente era atendida bajo una consigna equivalente a “sacársela de encima lo antes posible”.

Llegó mi número, saludé, tomé asiento e inicié mi trámite que requería rellenar un misterios formulario que hacía imposible el hacerlo por teléfono.

Describí exactamente el servicio que quería contratar a la funcionaria, quien comenzó a escribir cosas en la computadora. Primero que nada revisó en el sistema de aduana si mi teléfono estaba legal en el país. Cuando lo constató, mi hizo firmar un documento de Ancel que decía que mi teléfono estaba legal (extraño, dado que uno pensaría que el sistema de la Dirección Nacional de Aduanas es más importante que el de una empresa de telefonía) y se dirigió al fondo del local.

Volvió con un formulario a rellenar donde decía que se me diera de alta un servicio de datos “WAP GPRS”. Esto me extrañó y le comenté que yo quería un plan 3G, no WAP. Además, dado que el motivo por el cual no se podía hacer el trámite por teléfono era para firmar este papel, me resultaba importante hacerlo bien.

La funcionaria únicamente me contestó que el formulario no estaba actualizado. Que ella seleccionaba una opción (aparentemente aleatoria y distinta de lo que yo estaba solicitando), y que luego me darían de alta el servicio que yo había solicitado.

Esto realmente de desconcertó. ¿Para qué me harían firmar esto? Es un formulario que dice que se me active un servicio que no es el que yo estoy solicitando, para que luego se me active algo distinto a lo que el formulario firmado requiere. ¿Fue por esto que se me solicitó presentarme en persona? ¿Para firmar un formulario que no tiene sentido o validez?.

Me pregunto: dado el grado de informalidad de éste tramite, ¿no se podría haber hecho por teléfono?

Tras firmar, y continuando con el trámite, solicité a la señorita que se registrara el IMEI de mi nuevo celular en el sistema de Ancel. Ella me respondió que eso no era necesario y que la conexión 3G debería funcionar igual. Una vez más, dudo de la legalidad de las acciones que se me está solicitando hacer.

Ciertamente existe un motivo por el cual Ancel registra los números IMEI de los teléfonos, el cual debe ser validado contra el sistema de la Dirección Nacional de Aduanas. Asimismo, tengo entendido que el servidor al cual uno se conecta valida el IMEI del módem, y si éste no está registrado, la conexión es rechazada.

Más allá de estos dos motivos, mi celular registrado se encuentra roto y no lo estoy usando más, por lo cual lo lógico es que Ancel tenga mi nuevo IMEI registrado. Tras explicar esto a la funcionaria de Ancel, su respuesta fue épica:

Uff… Me la complicás“.

La respuesta me dejó perplejo. Dada la forma en que se me estaba tratando a mi y a los demás clientes presentes, ya sospechaba que los funcionarios querían irse, pero su respuesta, incluyendo una queja por la tarea que le estaba solicitando, una tarea no solo es parte de su trabajo, sino que también estoy seguro de que es tanto política de Ancel como obligación por parte de la Dirección Nacional de Aduanas, me dejó perplejo. No estaba solicitando nada más que la funcionaria realizara su trabajo. Sigo sin poder creer su respuesta. Debí haberle preguntado su nombre en ese momento para publicarlo aquí.

Habiendo terminado el trámite, firmando dos documentos, uno redundante y otro solicitando un servicio que no era el que yo quería adquirir, pregunté a la funcionaria cuál sería mi nombre de usuario y mi contraseña para hacer uso del servicio. Nuevamente se manifestó la desinformación de los funcionarios que en este local de Ancel trabajan. Me respondió que estos datos no eran necesarios, que el módem se conecta “solo”. “Mágicamente”, faltó agregarle.

Tras insistir, y probablemente cansada de tener que contestar mis preguntas, la funcionaria se dirigió al fondo y me envió al “técnico”. El “técnico”, me dijo que éste no era un local técnico (lo cual me pareció muy curioso, dado que después de todo ¿qué estaba haciendo esa persona ahí entonces?) y que me dirigiera a otro lugar a hacer otra cola.

Resignado le agradecí y me dirigí al otro local, en frente al Montevideo Shopping. En éste local, directamente no se me dejó ingresar. Si bien éste local atiende hasta las 19:00 horas, resulta que 18:15 (hora en la que me presenté) dejan de entregar números, prohibiendo el acceso a clientes. Literalmente, un Guardia me bloqueó la puerta y no me permitió entrar.

Siendo cliente de Ancel desde hace aproximadamente 10 años, nuevamente no podía creer mi asombro al ser bloqueado de acceder mediante un Guardia, cual si fuera un mendigo o un ladrón. Intenté explicar que mi trámite había comenzado en otro local y que solo era un momento, pero fue en vano. El Guardia solo repetía lo que le ordenaron repetir: “no entregamos más números”, aunque sean las 18:15 horas.

Ya cansado de esperar, firmar cosas sin sentido, ser testigo de las prácticas de dudosa legalidad de los funcionarios de Ancel y tener que trasladarme físicamente de un local a otro para poder completar un único un trámite, me retiré.

¿Cuál es estado de mi trámite hoy? Pues, tengo el servicio contratado, se me está cobrando y no puedo hacer uso de él debido a que no se me otorgan las credenciales necesarias para configurar mi equipo.

Realmente me encuentro en un estado muy incómodo, el cual debo solucionar lo antes posible. Algo que desafortunadamente no puedo anhelar, debido a que sé a qué me enfrentaré durante mi próxima visita: más espera, más prácticas de dudosa legalidad por parte de los funcionarios de Ancel y más burocracia.

¿Por qué estoy escribiendo esto? Porque estoy cansado de que a los consumidores Uruguayos se nos trate de la manera que se nos está tratando por las empresas orientadas a consumidores finales, sean estas tanto privadas como públicas. Estoy cansado de que los Uruguayos nos quedemos callados cuando una empresa de la cual somos clientes y a la cual estamos pagando todos los meses nos provea servicios malos, caros y con mala disposición.

El caso particular de Ancel, AntelData y Antel en general es particularmente lamentable. En todo momento traté a los funcionarios con el debido respeto y amabilidad, como quien no quiere molestar. Incluso, en todo momento repetía que yo mismo configuraría mi módem, que no era necesario que ellos lo hicieran. Únicamente deseaba el alta del servicio en el sistema y mis credenciales.

Lo que encontré a cambio fueron largas esperas y atención de mala gana, como si uno estuviera molestando a los funcionarios de la empresa. Quiero pensar que todo esto fue una situación excepcional, pero francamente, tras visitar dos locales distintos en dos días, me cuesta creerlo.

Dada la forma en que los funcionarios de Ancel nos tratan a nosotros, sus clientes, así como la forma en que incurren en prácticas de dudosa legalidad con toda normalidad y sin ningún tipo de preocupación, sobre todo tratándose de una empresa del Estado, entonces quizás deberían dejar de autodenominarse “la Empresa de los Uruguayos”.

Share/Bookmark

por varrojo, el 4 de marzo de 2010 a las 00:26

3 de marzo de 2010

Marcos Crispino

En busca de código repetido

Uno de los problemas que más me quitan el sueño en los últimos tiempos, es el código repetido.

¿Por qué tener código repetido es un problema? La respuesta creo que es conocida por todos. El problema es que eventualmente las distintas versiones que se tienen se terminan desfazando, y empiezan a aparecer errores por tocar solo una. Además después de un cierto tiempo, es muy difícil saber cual de todas las versiones es la correcta, porque en general los cambios no se hacen en todas parejo.

Entonces, ¿cuanto código repetido es aceptable? Esta pregunta indudablemente es más abierta, y pueden haber diferentes criterios. ¿Una línea de código duplicada está bien?

Por ejemplo, si tengo el siguiente código (GeneXus 9.0), ¿está bien?:
if DocImpres = 'S'
    call(WGLLogDe,&msg1, &msg2, 'OC', 'CMANUDOCOC', &GlLogRef, '', &confirmo)
    if &confirmo = 'N'
        Call(PGLog, &msg1, &msg2, 'OC', 'CMANUDOCOC', &GlLogRef, '', &PedirDet)
    endif
else
    Call(PGLog, &msg1, &msg2, 'OC', 'CMANUDOCOC', &GlLogRef, '', &PedirDet)
endif
Nótese que los dos call al procedure GLog son idénticos... Además, los literales 'OC' y 'CMANUDOCOC' se usan varias veces en el código...

Haciendo algunos cambios al programa para eliminar estas repeticiones, llegamos a algo así:
&logGrabado = 'N'
&GLLogSis = 'OC'
&TpoModId = 'CMANUDOCOC'
if DocImpres = 'S'
    &logGrabado = udp(WGLLogDe, &msg1, &msg2, &GLLogSis, &TpoModId, &GlLogRef, '')
endif
if &logGrabado = 'N'
    Call(PGLog, &msg1, &msg2, &GLLogSis, &TpoModId, &GlLogRef, '', '')
endif
¿Es mejor que el código anterior? Yo creo que sí, pero seguramente para un caso tan simple haya discrepancias...

Pienso que cuando se trata de 2 o más líneas de código es más fácil estar de acuerdo que no es bueno tener dicho código repetido.

Ahora, el problema, es como detectar esta situación.

Cuando el código repetido está dentro del mismo objeto, entonces es bastante fácil de detectar. No es trivial cuando se tienen programas grandes (más de 500 líneas por ejemplo), pero es posible.

El mayor problema es cuando el código repetido está en varios objetos. En esos casos no es para nada fácil de detectar.

Pienso que se podría automatizar, aunque no parece ser trivial. Algunas heurísticas que se me ocurre se podrían utilizar:
  • Analizar las navegaciones de los objetos, para ver si hay navegaciones iguales. Esos objetos son candidatos a analizar. No necesariamente quiere decir que se pueda mejorar el código, pero sí vale la pena revisarlo.
  • En general cuando se da que hay código repetido, el mismo está en el entorno de la llamada a un objeto, o en torno al uso de un determinado atributo. Por ejemplo, tengo un procedimiento que me devuelve un valor, y luego hago algo con dicho valor, pero en varios lugares lo que hago es exáctamente lo mismo...
¿Alguien ha tenido la misma inquietud? ¿Existe alguna herramienta que me permita buscar en una KB GeneXus los posibles problemas de código repetido?

por noreply@blogger.com (Marcos Crispino), el 3 de marzo de 2010 a las 17:46

2 de marzo de 2010

Alejandro Segovia

Discontinuación de Windows y Rechazo al Cambio

El otro día leía en OSNews acerca del fin de soporte inminente para varias versiones Windows, incluyendo Windows XP Service Pack 2, Windows 2000 y Windows Vista RTM, donde a los usuarios de dichos sistemas operativos se les recomienda cambiar su sistema para “mantenerse seguros, al día y felices”.

Desde hace tiempo quité completamente a Windows de mi stack tecnológico (por así llamarlo), no haciendo uso de él para más que para proyectos puntuales del trabajo (o algún juego puntual de vez en cuando que no anda en Linux). Debo reconocer, sin embargo, como la gente sigue haciendo uso de Windows XP.Linux Logo

Recuerdo en los viejos tiempos, cuando yo era recien un novato en Linux (joven e ingenuo). En aquellos tiempos usaba Debian en mi viejo laptop Toshiba y quería convencer a la gente de probar hacer lo mismo. Quería mostrarles que existía una forma diferente de hacer las cosas. Que habían alternativas. Que probaran Linux.

Sin embargo, casi siempre me encontraba con una negativa…

“Que eso es complicado, que nadie lo usa, que eso no anda, que no me andan los juegos, que no me anda el Visual Studio, etc, etc…”

Si hoy me preguntás si perdía el tiempo, te diré que no.

No me arrepiento de haber al menos intentado, ya que durante esos años aprendí una cosa muy importante: la gente rechaza el cambio. Le tiene pavor.

He llegado a escuchar argumentos de todo tipo en contra del uso de Linux, desde fanatismo puro hasta argumentos sólidos y lógicos. Si bien el resultado era siempre el mismo, realmente me puse a pensar si había alguna razón de fondo común a por qué la gente parecía tan cerrada en este aspecto.

No logré entenderlo hasta que Windows Vista salió al mercado. Cuando Vista salió, a Microsoft le pasó exactamente lo mismo. Fue ahí cuando me dí cuenta: lo difícil de convertir la gente a Linux no era el hecho de “vender” Linux, sino el hecho de pedirles que que prueben algo distinto de lo que conocen.

Cuando Microsoft se encontró con este problema, ellos lo resumieron en una frase que hasta hoy recuerdo:

“Nuestra mayor competencia es nuestra base instalada.”

El reto de Vista era hacer que la gente dejara XP, tarea en la cual por cierto, fracasó miserablemente. Windows XP vivió y vivirá más que su supuesto sucesor.

El problema XP Wallpaper Rotodel rechazo al cambio es un golpe duro para Microsoft, quien se ve forzado a realizar soporte a un código base de al menos 9 años de antigüedad, todo parcheado por donde se lo vea y con afluentes de código de hace hasta 15 años. Es una pesadilla, es sorprendente que algo así no se caiga a pedazos.

Sin embargo, la gente “está contenta” con “su” XP y si por ellos fuera, no lo cambiarían ni ahora ni en 9 años más. La gente está arraigada. Ni siquiera gente que hoy es estudiante de Ingeniería en Informática puede sacarse el rechazo y miedo que le genera tener que “empezar de cero”.

Yo aprendí la lección durante un par de años de intentos de mostrar otro camino a la gente. Hoy mi postura es muy distinta. Sigo siendo un Linuxero, pero también soy abierto a otras alternativas (como Mac). No condeno a quien utiliza Windows, ni tampoco intento de convencerlo de que se “convierta” a Linux.

Si alguien viene y me dice “quiero probar otra cosa, qué me sugerís?”, estoy ahí para ayudar a dar los primeros pasos. Todo, absolutamente todo lo demás es perder tiempo.

Cuanto más se intente imponer que los usuarios cambien, más se van a arraigar a las cosas que utilizan hoy y más van a rechazar el cambio. Lo mejor que sepan que existe otra cosa (ya sea porque nosotros, los “convertidos”, las usamos, o porque organizamos eventos, o por lo que sea) y que luego el deseo de probar salga de cada uno.

Linux tiene todo el tiempo del mundo… Windows, no tanto.

Share/Bookmark

por varrojo, el 2 de marzo de 2010 a las 17:00

Apple demanda a HTC con 20 patentes!

Apple al parecer se pone de mal humor cuando los competidores imitan la tecnología del iPhone, ya que está demandando a HTC por la violación de no menos de 20 patentes!

De acuerdo con Apple, la demanda involucra violaciones a patentes de “interfaz de usuario, arquitectura subyacente y Hardware” y reclama como compensación una prohibición de importación y venta de dispositivos HTC en EEUU, además de una montaña de dinero.

Steve Jobs, CEO de Apple, tuvo para comentar:

“We can sit by and watch competitors steal our patented inventions, or we can do something about it. We’ve decided to do something about it. We think competition is healthy, but competitors should create their own original technology, not steal ours.”

Mientras que algunas patentes aplicadas en las demanda parecen bastante bajo nivel (cómo “System And Method For Managing Power Conditions Within A Digital Camera Device”) otras patentes son bastante peligrosas para los Informáticos (como por ejemplo: “Object-Oriented Graphic System” u “Object-Oriented Event Notification System With Listener Registration Of Both Interests And Methods”).

Veremos en qué termina todo esto dentro de los próximos meses.

En Gizmodo pueden encontrar una lista completa de las patentes aplicadas en la demanda.

Share/Bookmark

por varrojo, el 2 de marzo de 2010 a las 16:06

1 de marzo de 2010

Alejandro Revilla

What is jCard?

/by apr/

As a follow-up to the initial post about jCard and jPTS, I’d like to explain what is jCard after all.

jCard is an interface between the ISO-8583 world and a double-entry accounting system.

– or better yet –

jCard is an interface between the ISO-8583 v2003 based jPOS-CMF world and a
multi-layer, multi-currency general purpose double-entry accounting system (miniGL).

Here is an the initial ER diagram of the core components that we used at design time, although somehow changed to support customer’s requirements, it still gives you the idea of how the pieces fit together:

You can see here that an Issuer has CardProducts which in turn has Cards. A Card is our handle to the CardHolder which in turn can have multiple GL Accounts (think Checking, Savings, Stored Value accounts).

Imagine this little chart of accounts for a pre-paid card:

As seen from jCard’s perspective, a deposit transaction will debit our ‘Received money’ account (an asset) and credit the Cardholder’s SV account (it’s a liability now for us).

So a deposit transaction will look like this:

USD 100 goes to the ‘Received Money’ account and 100 to the Cardholder’s account.

If you enlarge the picture, you’ll see a little ‘840′ number to the right of the account code, i.e. 11.001.00840, that’s our layer (in this case the accounting USD layer, 840 is the ISO-4217 currency number).

Here is a purchase transaction that involve some fees, followed by a reversal:

You can see we just change who we owe to, instead of owing this money to the cardholder, we owe it now to the acquirer (or merchant/branch, depending on the situation).

The ISO-8583 side honors the jPOS CMF, so this purchase transaction looks like this:

       <isomsg direction="incoming">
         <field id="0" value="2200"/>
         <field id="2" value="604955_________0001"/>
         <field id="3" value="013000"/>
         <field id="4" currency="840" type="amount" value="20.00"/>
         <field id="7" value="0301173541"/>
         <field id="11" value="000000000083"/>
         <field id="12" value="20100301173541"/>
         <field id="13" value="000301"/>
         <field id="14" value="1012"/>
         <field id="17" value="0301"/>
         <field id="32" value="000001"/>
         <field id="37" value="010535141630"/>
         <field id="41" value="29110001        "/>
         <field id="42" value="001001"/>
         </isomsg><isomsg id="43">
           <field id="2" value="jCard Selftest system"/>
           <field id="4" value="Montevideo"/>
           <field id="5" value="MV "/>
           <field id="7" value="UY "/>
         </isomsg>
         <field id="46" value="07D84020000005000000001D840200000050"/>

This particular CardProduct has a flat fee of USD 3.50 plus a 3.25% for CashAdvance transactions, this is configured like this:

mysql> select * from cardproduct_fees where id = 1;
+----+--------+----------------------+
| id | fee    | type                 |
+----+--------+----------------------+
|  1 | 3.2500 | CashAdvance.%.840    |
|  1 | 3.5000 | CashAdvance.flat.840 |
+----+--------+----------------------+

that’s why we ended-up charging USD 24.65.

For those of you familiar with jPOS, looking at its TransactionManager main configuration may give you an idea of what we are talking about here:

<txnmgr class="org.jpos.transaction.TransactionManager" logger="Q2">
 <property name="queue" value="JCARD.TXN" />
 <property name="sessions" value="2" />
 <property name="debug" value="true" />
 
 <participant class="org.jpos.jcard.PrepareContext" logger="Q2" realm="PrepareContext" />
 <participant class="org.jpos.transaction.Open" logger="Q2" realm="open">
  <property name="checkpoint" value="open" />
  <property name="timeout" value="300" />
 </participant>
 
 <participant class="org.jpos.jcard.Switch" logger="Q2" realm="Switch">
  <property name="100.30" 
           value="balanceinquiry prepareresponse logit close sendresponse" />
  <property name="100.00" 
           value="authorization prepareresponse logit close sendresponse" />
  <property name="100.02" 
           value="auth-void prepareresponse logit close sendresponse" />
  <property name="100.20" 
           value="refund prepareresponse logit close sendresponse" />
  <property name="100.22" 
           value="refund-void prepareresponse logit close sendresponse" />
 
  <property name="200.00" 
           value="financial prepareresponse logit close sendresponse" />
  <property name="200.01" 
           value="financial prepareresponse logit close sendresponse" />
  <property name="200.02" 
           value="purchase-void prepareresponse logit close sendresponse" />
  <property name="200.20" 
           value="financial-refund prepareresponse logit close sendresponse" />
  <property name="200.21" 
           value="financial-deposit prepareresponse logit close sendresponse" />
  <property name="200.22" 
           value="financial-refund-void prepareresponse logit close sendresponse" />
  <property name="200.40" 
           value="transfer prepareresponse logit close sendresponse" />
 
  <property name="220.00.0000" 
           value="completion prepareresponse logit close sendresponse" />
  <property name="220.20.0000" 
           value="refund-completion prepareresponse logit close sendresponse" />
  <property name="220.00.1000" 
           value="force-post prepareresponse logit close sendresponse" />
  <property name="220.00.2000" 
           value="force-post prepareresponse logit close sendresponse" />
  <property name="220.20.1000"
           value="refund-force-post prepareresponse logit close sendresponse" />
  <property name="220.20.4500"
           value="refund-force-post prepareresponse logit close sendresponse" />
 
  <property name="420.00.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="420.01.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="420.02.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="420.20.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="420.21.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="420.40.0000" 
           value="reversal prepareresponse logit close sendresponse" />
  <property name="304.301.CUSTOMER"  
           value="add_customer_record prepareresponse logit close sendresponse" />
  <property name="304.301.MERCHANT"  
           value="add_merchant_record prepareresponse logit close sendresponse" />
  <property name="unknown"  
           value="notsupported prepareresponse close sendresponse" />
 </participant>
 
 <participant class="org.jpos.jcard.ProtectDebugInfo" logger="Q2" realm="ProtectDebug" />
 <participant class="org.jpos.transaction.Debug" logger="Q2" realm="debug" />
 
 <group name="notsupported">
  <participant class="org.jpos.jcard.NotSupported" logger="Q2" 
    realm="not-supported" />
 </group>
 
 <group name="balanceinquiry">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13,AMOUNT,PAN,41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
  <participant class="org.jpos.jcard.BalanceInquiry" 
    logger="Q2" realm="balance-inquiry" />
 </group>
 
 <group name="authorization">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
   <property name="checkpoint"   value="check-card" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal">
   <property name="checkpoint"   value="check-terminal" />
  </participant>
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer">
   <property name="checkpoint"   value="check-acquirer" />
  </participant>
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account">
   <property name="checkpoint"   value="select-account" />
  </participant>
  <participant class="org.jpos.jcard.CheckPreviousReverse" 
    logger="Q2" realm="check-previous-reverse">
   <property name="checkpoint"   value="check-previous-reverse" />
  </participant>
  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity">
   <property name="checkpoint"  value="check-velocity" />
  </participant>
  <participant class="org.jpos.jcard.Authorization" 
    logger="Q2" realm="authorization">
   <property name="checkpoint"   value="authorization" />
  </participant>
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 <group name="financial">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.CheckPreviousReverse" 
    logger="Q2" realm="check-previous-reverse" />
  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity" />
  <participant class="org.jpos.jcard.Financial" 
    logger="Q2" realm="financial" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 
 <group name="refund">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity" />
  <participant class="org.jpos.jcard.Refund" logger="Q2" realm="refund" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 <group name="financial-refund">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity" />
  <participant class="org.jpos.jcard.FinancialRefund" 
   logger="Q2" realm="financial-refund" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 
 <group name="financial-deposit">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.FinancialDeposit" 
   logger="Q2" realm="financial-deposit" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 
 <group name="reversal">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 25,41, ORIGINAL_DATA_ELEMENTS" />
   <property name="optional"  value="17,24,25,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="window" value="259200" />
   <property name="fields" value="stan, amount, currency, card, original-tx-timestamp" />
  </participant>
  <participant class="org.jpos.jcard.Reverse" logger="Q2" realm="reverse" />
 </group>
 
 <group name="completion">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN,25,38,41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="original-itc" value="100.00" />
   <property name="window" value="2592000" />
   <property name="fields" value="card, approvalNumber, currency" />
  </participant>
  <participant class="org.jpos.jcard.Completion" logger="Q2" realm="reverse" />
 </group>
 
 <group name="refund-completion">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13,AMOUNT,PAN,25,38,41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="original-itc" value="100.20" />
   <property name="window" value="2592000" />
   <property name="fields" value="card, approvalNumber, currency" />
  </participant>
  <participant class="org.jpos.jcard.Completion" logger="Q2" realm="completion" />
 </group>
 
 <group name="force-post">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN,25,41" />
   <property name="optional"  value="17,24,32,37,38,39,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.ForcePost" 
      logger="Q2" realm="force-post" />
 </group>
 <group name="refund-force-post">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN,25,41" />
   <property name="optional"  value="17,24,32,37,38,39,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.RefundForcePost" 
      logger="Q2" realm="refund-force-post" />
 </group>
 
 <group name="transfer">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />
  <participant class="org.jpos.jcard.CheckPreviousReverse" 
    logger="Q2" realm="check-previous-reverse" />
  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity" />
  <participant class="org.jpos.jcard.Transfer" 
    logger="Q2" realm="transfer" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>
 </group>
 
 <group name="purchase-void">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41, ORIGINAL_DATA_ELEMENTS" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="window" value="259200" />
   <property name="fields" value="stan, amount, currency, card, original-tx-timestamp" />
   <property name="original-itc" value="200.00" />
  </participant>
  <participant class="org.jpos.jcard.Void" logger="Q2" realm="void" />
 </group>
 <group name="auth-void">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41, ORIGINAL_DATA_ELEMENTS" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="window" value="259200" />
   <property name="fields" value="stan, amount, currency, card, original-tx-timestamp" />
   <property name="original-itc" value="100.00" />
  </participant>
  <participant class="org.jpos.jcard.Void" logger="Q2" realm="void" />
 </group>
 
 <group name="close">
  <participant class="org.jpos.transaction.Close" logger="Q2" realm="open">
   <property name="checkpoint" value="close" />
  </participant>
 </group>
 <group name="refund-void">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41, ORIGINAL_DATA_ELEMENTS" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="window" value="259200" />
   <property name="fields" value="stan, amount, currency, card, original-tx-timestamp" />
   <property name="original-itc" value="100.20" />
  </participant>
  <participant class="org.jpos.jcard.Void" logger="Q2" realm="void" />
 </group>
 <group name="financial-refund-void">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41, ORIGINAL_DATA_ELEMENTS" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.CheckCard" 
      logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>
  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />
  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />
  <participant class="org.jpos.jcard.FindOriginal" logger="Q2" realm="findoriginal">
   <property name="window" value="259200" />
   <property name="fields" value="stan, amount, currency, card, original-tx-timestamp" />
   <property name="original-itc" value="200.20" />
  </participant>
  <participant class="org.jpos.jcard.Void" logger="Q2" realm="void" />
 </group>
 
 <group name="prepareresponse">
  <participant class="org.jpos.jcard.PrepareResponse" logger="Q2" realm="prepareresponse">
   <property name="locale" value="JCARD" />
   <property name="checkpoint"   value="prepare-response" />
  </participant>
 </group>
 <group name="logit">
  <participant class="org.jpos.jcard.LogIt" logger="Q2"
    realm="log-it">
   <property name="checkpoint"   value="log-response" />
  </participant>
 </group>
 
 <group name="sendresponse">
  <participant class="org.jpos.jcard.SendResponse" logger="Q2" realm="sendresponse" />
 </group>
 
 <group name="add_customer_record">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="7,11,12,24,101" />
   <property name="optional"  value="2,72,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.AddCustomer" 
      logger="Q2" realm="add-customer">
   <property name="chart"        value="jcard" />
   <property name="customers-account" value="21" />
   <property name="issuer" value="1" />
   <property name="card-product" value="1" />
   <property name="final-account" value="00" />
   <property name="account-description-00" value="Stored Value" />
   <property name="account-currency-00" value="840" />
   <property name="account-additional-mapping-00" value="31, 32, 33, 34, 35, 36" />
 
   <property name="final-account" value="40" />
   <property name="account-description-40" value="Stored Points" />
   <property name="account-currency-40" value="840" />
   <property name="account-additional-mapping-40" value="" />
   <property name="kid" value="&KID;" />
  </participant>
 </group>
 
 <group name="add_merchant_record">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="7,11,12,24,101" />
   <property name="optional"  value="2,32,42,72,111" />
  </participant>
  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>
  <participant class="org.jpos.jcard.AddMerchant" 
      logger="Q2" realm="add-merchant">
  </participant>
 </group>
</txnmgr>

So the previous transaction was a 200.01 (MTI=200, Processing code 013000), so we processed the following groups:

  • financial
  • prepareresponse
  • logit
  • sendresponse

The financial group looks like this:

First, we perform some sanity checks, we verify that the mandatory fields are present, we allow some optional fields too.

<group name="financial">
  <participant class="org.jpos.jcard.CheckFields" logger="Q2" realm="CheckRequiredFields">
   <property name="mandatory" value="PCODE,7,11,12,13, AMOUNT, PAN, 41" />
   <property name="optional"  value="17,24,32,37,42,43,46,60,63,111" />
  </participant>
</group>

Then we create a TranLog record (that’s our master transaction log file)

  <participant class="org.jpos.jcard.CreateTranLog" logger="Q2" 
      realm="create-tranlog">
   <property name="queue"        value="JCARD.TXN" />
   <property name="space"        value="tspace:default" />
   <property name="capture-date" value="capture-date" />
   <property name="checkpoint"   value="create-tranlog" />
   <property name="node"         value="01" />
  </participant>

We check that the card exists, it’s valid, belongs to a CardHolder, etc. We do this in a PCI compliant way, that ‘KID’ configuration there is the DUKPT BDK Key ID.

  <participant class="org.jpos.jcard.CheckCard"    
   logger="Q2" realm="checkcard">
   <property name="kid" value="&KID;" />
  </participant>

The terminal has to be valid too:

  <participant class="org.jpos.jcard.CheckTerminal"    
   logger="Q2" realm="checkterminal" />

And so is the acquirer (we’ll have to pay them at some point)

  <participant class="org.jpos.jcard.CheckAcquirer"    
   logger="Q2" realm="checkacquirer" />

We know the Card, so we know the CardHolder. We know the CardHolder has accounts, and based on the processing code (data element 3), we choose which account to use (checking, saving, credit, stored value, loyalty, whatever)

  <participant class="org.jpos.jcard.SelectAccount" 
    logger="Q2" realm="select-account" />

It can happen under certain scenarios (mostly due to small network outages) that we could receive a reversal for a given transaction before or almost at the same time as the transaction itself, so we check if this transaction was previously reversed:

  <participant class="org.jpos.jcard.CheckPreviousReverse" 
    logger="Q2" realm="check-previous-reverse" />

Then, based on the CardProduct, we can perform multiple velocity checks:

  <participant class="org.jpos.jcard.CheckVelocity"    
   logger="Q2" realm="checkvelocity" />

And now we are ready to generate the GL transaction and compute the balances after that.

  <participant class="org.jpos.jcard.Financial" 
    logger="Q2" realm="financial" />
  <participant class="org.jpos.jcard.ComputeBalances" 
      logger="Q2" realm="compute-balances">
    <property name="checkpoint" value="compute-balances" />
  </participant>

Here is the source code for org.jpos.jcard.Financial

public class Financial extends Authorization {
    public int prepare (long id, Serializable context) {
        return super.prepare (id, context);
    }
    protected short getLayerOffset() {
        // financial transactions goes to the main layer for the
        // given currency
        return 0;  
    }
    protected String getTransactionName() {
        return "Financial";
    }
}

Pretty simple, huh? Please pay attention to that ‘getLayerOffset()’ method that returns 0.

The Authorization participant is slightly more complex:

public class Authorization extends JCardTxnSupport {
    public static final String FEE_PREFIX = "CashAdvance";
 
    public Authorization() {
        super();
    }
    public int prepare (long id, Serializable context) {
        Context ctx = (Context) context;
        try {
            ctx.checkPoint ("authorization-start");
            TranLog tl  = (TranLog) ctx.get (TRANLOG);
            GLSession gls = getGLSession(ctx);
            ISOMsg m = (ISOMsg) ctx.get (REQUEST);
            Card card = (Card) ctx.get (CARD);
            CardHolder cardHolder = (CardHolder) ctx.get (CARDHOLDER);
            Issuer issuer = (Issuer) ctx.get (ISSUER);
 
            String accountType = ctx.getString (PCODE_ACCOUNT_TYPE);
            BigDecimal amount = (BigDecimal) ctx.get (AMOUNT);
            BigDecimal acquirerFee = getAcquirerFee (m);
            BigDecimal issuerFee = ZERO;
 
            assertNotNull (issuer, INVALID_REQUEST, "Invalid Issuer");
            assertNotNull (card, INVALID_REQUEST, "Invalid Card");
            assertNotNull (card.getCardProduct(), INVALID_REQUEST, "Invalid CardProduct");
            assertNotNull (
                 card.getCardProduct().getIssuedAccount(), INVALID_REQUEST, 
                "Invalid CardProduct Issued Account"
            ); 
            assertNotNull (cardHolder, INVALID_REQUEST, "Invalid CardHolder");
            assertNotNull (amount, INVALID_AMOUNT);
            assertFalse (ZERO.equals (amount), INVALID_AMOUNT, "Zero amount not valid");
            assertNotNull (accountType,
                INVALID_REQUEST, "Invalid processing code"
            );
            assertFalse(REFUND_ACCOUNT_TYPE.equals (accountType),
                INVALID_REQUEST, "Refund account not allowed"
            );
            String acctid = accountType+"."+ctx.getString(CURRENCY);
            FinalAccount acct = (FinalAccount) 
                cardHolder.getAccounts().get (acctid);
 
            assertNotNull (acct, 
                ACCOUNT_NOT_FOUND, 
                "Account type '"+acctid+"' is not defined");
 
            Journal journal = issuer.getJournal();
            assertNotNull (
                journal, SYSERR_DB, 
                "Journal not found for issuer " + issuer.getId() + " ("
                + issuer.getName() + ")"
            );
 
            ctx.checkPoint ("authorization-pre-lock-journal");
            gls.lock (journal, acct);
            ctx.checkPoint ("authorization-post-lock-journal");
 
            short currency = getCurrency (ctx.getString(CURRENCY));
            short[] realAndPending = new short[] {
                currency, (short) (currency + PENDING_OFFSET)
            };
            BigDecimal balance = gls.getBalance (journal, acct, realAndPending);
            ctx.checkPoint ("authorization-compute-balance");
            BigDecimal amountPlusFees = amount.add(acquirerFee);
 
            ctx.put (ACCOUNT, acct);
            String surchargeDescription = null;
            if (amountPlusFees.compareTo (balance) > 0) {
                BigDecimal creditLine = gls.getBalance (
                    journal, acct, 
                    new short[] { (short)(currency+CREDIT_OFFSET) }
                );
                ctx.checkPoint ("authorization-get-credit-line");
                if (acct.isDebit())
                    creditLine = creditLine.negate();
 
                StringBuilder sb = new StringBuilder();
                issuerFee = issuerFee.add(calcSurcharge (ctx, card, amount, FEE_PREFIX, sb));
                if (sb.length() > 0)
                    surchargeDescription = sb.toString();
                amountPlusFees = amountPlusFees.add (issuerFee);
                if (!isForcePost() && amountPlusFees.compareTo
                    (balance.add(creditLine)) >= 0) 
                {
                    throw new BLException (NOT_SUFFICIENT_FUNDS, 
                        "Credit line is " + creditLine 
                       +", issuer fee=" + issuerFee); 
                }
            }
            Acquirer acquirer = (Acquirer) ctx.get (ACQUIRER);
 
            GLTransaction txn = new GLTransaction (
                getTransactionName() + " " + Long.toString(id)
            );
            txn.setPostDate ((Date) ctx.get (CAPTURE_DATE));
            txn.createDebit (
                acct, amountPlusFees, null, 
                    (short) (currency + getLayerOffset())
            );
            txn.createCredit (
                acquirer.getTransactionAccount(), amount, 
                null, (short) (currency + getLayerOffset())
            );
            if (!ZERO.equals(issuerFee)) {
                txn.createCredit (
                    card.getCardProduct().getFeeAccount(), issuerFee, 
                    surchargeDescription, (short) (currency + getLayerOffset())
                );
                ctx.put (ISSUER_FEE, issuerFee);
            }
            if (!ZERO.equals(acquirerFee)) {
                txn.createCredit (
                    acquirer.getFeeAccount(), acquirerFee, 
                    null, (short) (currency + getLayerOffset())
                );
                ctx.put (ACQUIRER_FEE, acquirerFee);
            }
            gls.post (journal, txn);
            ctx.checkPoint ("authorization-post-transaction");
            tl.setGlTransaction (txn);
            ctx.put (RC, TRAN_APPROVED);
            ctx.put (APPROVAL_NUMBER, getRandomAuthNumber());
            return PREPARED | NO_JOIN;
        } catch (ObjectNotFoundException e) {
            ctx.put (RC, CARD_NOT_FOUND);
        } catch (GLException e) {
            ctx.put (RC, NOT_SUFFICIENT_FUNDS);
            ctx.put (EXTRC, e.getMessage());
        } catch (BLException e) {
            ctx.put (RC, e.getMessage ());
            if (e.getDetail() != null)
                ctx.put (EXTRC, e.getDetail());
        } catch (Throwable t) {
            ctx.log (t);
        } finally {
            checkPoint (ctx);
        }
        return ABORTED;
    }
    public void commit (long id, Serializable context) { }
    public void abort  (long id, Serializable context) { }
 
    protected short getLayerOffset() {
        return PENDING_OFFSET;
    }
    protected String getTransactionName() {
        return "Authorization";
    }
    protected BigDecimal calcSurcharge 
        (Context ctx, Card card, BigDecimal amount, StringBuilder detail) 
    {
        BigDecimal issuerFee = ZERO;
        Map<string ,BigDecimal> fees = card.getCardProduct().getFees();
        BigDecimal flatFee = fees.get(
            FEE_PREFIX + FEE_FLAT + ctx.getString(CURRENCY)
        );
        BigDecimal percentageFee = fees.get(
            FEE_PREFIX + FEE_PERCENTAGE + ctx.getString(CURRENCY)
        );
        if (flatFee != null) {
            issuerFee = issuerFee.add (
                flatFee.setScale(2, ROUNDING_MODE)
            );
            detail.append ("Surcharge: $");
            detail.append (flatFee);
        }
        if (percentageFee != null) {
            issuerFee = issuerFee.add (
                amount.multiply(
                    percentageFee.movePointLeft(2)
                ).setScale(2, ROUNDING_MODE)
            );
            if (flatFee != null)
                detail.append ('+');
            else
                detail.append ("Surcharge: ");
            detail.append (percentageFee);
            detail.append ('%');
        }
        return issuerFee;
    }
    protected boolean isForcePost () {
        return false;
    }
}
</string>

In this case getLayerOffset() returns PENDING_LAYER (a constant set to 1000).

So what happens here is that when we perform an authorization, we impact the PENDING layer (i.e. 1840 if the transaction was in USD) instead of the ACCOUNTING layer (840).

When we compute the USD ACCOUNTING BALANCE, we check for transactions on the 840 layer, but when we check for the available balance, we take into account layer 840 merged with layer 1840 (this is why miniGL has layers).

So to recap, this is a financial transaction (MTI 200):

And here is an interesting sequence:

  • Pre-Auth USD 100
  • Void of the preauth
  • Reversal of the previous void (authorization becomes active again, if available funds permit)
  • Partial completion for USD 90

If you pay attention to the layers involved, you can see that the pre-auth works on layer 1840 while the completion works on 840, the accounting layer (offset=0).

We use that layers scheme to handle overdrafts and credit account (offset is 2000), so for a credit account, we pick the balances from 840,1840,2840 (provided the transaction is performed in USD).

jCard was developed in paralell with the jPOS CMF and the jCard selftest facility, based on jPOS-EE’s clientsimulator.

Whenever we touch a single line of it, we automatically run an extensive set of transactions that gives us some confidence that we are not introducing any major issue, i.e:

...
...
    77: Card 6009330000000020 - savings balance is 102     [OK] 50ms.
    78: Card 6009330000000020 - $1 from checking to savings with $0.50 fee [OK] 126ms.
    79: Card 6009330000000020 - savings balance is 104     [OK] 48ms.
    80: $95.51 from checking to savings with no fee (NSF)  [OK] 78ms.
    81: $95.01 from checking to savings with $0.50 fee (NSF) [OK] 75ms.
    82: $95.00 from checking to savings with $0.50 fee - GOOD [OK] 70ms.
    83: Card 6009330000000020 - savings balance is now 199 [OK] 111ms.
    84: Reverse previous transfer                          [OK] 57ms.
    85: Reverse previous transfer (repeat)                 [OK] 70ms.
    86: savings balance after reverse is 104               [OK] 58ms.
    87: Withdrawal $20 from credit account with 0.50 fee   [OK] 85ms.
    88: credit balance check                               [OK] 59ms.
    89: Reverse withdrawal                                 [OK] 57ms.
    90: credit balance check - should be back to 1000      [OK] 50ms.
    91: $100.00 from credit to checking with $0.75 fee - GOOD [OK] 138ms.
    92: Reverse transfer                                   [OK] 52ms.
    93: credit balance check - should be back to 1000      [OK] 57ms.
    94: POS Purchase $20 from credit account with 0.50 fee to be voided [OK] 107ms.
    95: Void previous transaction                          [OK] 51ms.
    96: Void repeat                                        [OK] 24ms.
    97: Auth for $100 from savings account, no fees        [OK] 82ms.
    98: Void completed auth                                [OK] 51ms.
    99: Void repeat                                        [OK] 29ms.
    100: Invalid completion for USD 90.00 (previously voided) [OK] 34ms.
    101: Reverse void                                       [OK] 56ms.
    102: Reverse void retransmission                        [OK] 32ms.
    103: completion for USD 90.00 (void has been reversed)  [OK] 48ms.
    104: completion for USD 90.00 retransmission            [OK] 38ms.
    105: check savings balance - should be $14.00           [OK] 110ms.
    106: Refund for $16                                     [OK] 70ms.
    107: Reverse previous refund                            [OK] 47ms.
    108: refund reversed, balance back to 0.00              [OK] 67ms.
...
...

I hope that this post can give you an idea of what jCard is and why we are sometimes quiet on the blog, we are having fun developing all this.

por apr, el 1 de marzo de 2010 a las 21:55

Jorge Oyhenard

Identificando mercados: Nichos rentables y como acelerar ingresos | Punta Demene 2010


Continuo haciendo referencia a las charlas del Punta Demene 2010, en esta oportunidad a la dictada por Martin Alurralde, @Talu de Conexur, quien hablo de Identificando mercados: Nichos rentables y como acelerar ingresos, que aunque su titulo este más que claro hablo de como identificar que mercados son los que pueden generar mayores ingresos a emprededores y webmaster en Internet, y como generar mas y mayores ingresos con las diferentes opciones existentes.

Sin duda un tema mas que interesante, del cual comparto sus diapositivas.

Identificando mercados: Nichos rentables y como acelerar ingresos

Post original de: Jorge Oyhenard

Identificando mercados: Nichos rentables y como acelerar ingresos | Punta Demene 2010

Artículos relacionados:

por Jorge Oyhenard, el 1 de marzo de 2010 a las 21:03

28 de febrero de 2010

Alejandro Segovia

La iPad, extrapolada

Continúan las bromas sobre la iPad en Internet :-P

iPad, Extrapolada

Vía Gizmodo.

Share/Bookmark

por varrojo, el 28 de febrero de 2010 a las 22:23

26 de febrero de 2010

Dario Clavijo

El lobby del copyright dice que el sofware libre amenaza al capitalismo























El lobby del copyright un grupito de locos que representan a la MPAA y la RIAA dice que el software libre atenta contra el capitalismo.
Primero el software libre era "comunista" ahora atenta contra el capitalismo.
Estos señores crearon un informe llamado "Special 301" donde tienen una lista de países como Brasil, Canada, España, Indonesia, India y otros.
Todos por impulsar el software libre a nivel del gobierno, según ellos lo que hace el software libre es debilitar el mercado del software privativo y devaluar la propiedad intelectual (o sea un derecho sobre un bien intangible como el conocimiento), ademas de negar a compañías que crean software privativo (ej microsoft) al mercado de las administraciones publicas.

En pocas palabras nos quieren forzar a que utilicemos el software que ellos quieren y paguemos por ello, esto desde mi punto de vista es un avasallamiento a la soberanía de los estados afectados por este tipo de políticas estúpidas imperialistas y es una violación de la libertad.

por Daedalus (Daedalus2027@gmail.com), el 26 de febrero de 2010 a las 18:55

Jorge Oyhenard

La línea del tiempo SEO | Punta Demene 2010


El 25 y 26 de febrero se está llevando a cabo el Demene Punta del Este 2010, segundo evento anual con una gran concurrencia de domainers del exterior, la región y Uruguay.

Vimos muchas charlas, con temas muy interesantes que citare oportunamente, pero para comenzar los dejo mi presentación que es la que tengo más a mano.

La línea de tiempo SEO

Bajo la consigna y creencia de que no creo en los Secretos del SEO me baso que los buenos resultados y buenas posiciones en el buscador se obtienen con la suma de muchos y pequeños pasos, donde lo que cuenta es el trabajo, paciencia y la suma de todo.

de pronto a quien no participo, no le queda claro todo lo otro que si hable en la charla, pero bueno … cumplo con los presente, y a los demás los esperamos el próximo año …

Descargar en PDF

Post original de: Jorge Oyhenard

La línea del tiempo SEO | Punta Demene 2010

Artículos relacionados:

por Jorge Oyhenard, el 26 de febrero de 2010 a las 17:54

Dario Clavijo

Ya soy Estudiante de la Facultad de Ingenieria













El pasado 23  pude anotarme en la Facultad de Ingeniería de la Universidad de la República en la carrera de Ingeniería en Computación.
Estoy muy contento porque es un cambio radical, porque cierro un ciclo después de nueve años dejando atrás un par de frustraciones en el its, pero abriendo otro y con muchas ganas de seguir adelante,muchas expectativas y curiosidad.

Veré que me depara el futuro...

por Daedalus (Daedalus2027@gmail.com), el 26 de febrero de 2010 a las 03:27

25 de febrero de 2010

Dario Clavijo

CrossCompilando en Debian

Embedian es el toolchain de debian para dispositivos embebidos este toolchain tiene soporte para las arquitecturas arm,mips,ia64,sparc, powerpc y m68k y que provee el paquete gcc en varias versiones para poder compilar para estas arquitecturas.

En este caso quiero crosscompilar para arm:

#apt-get install embedian-tools

Tenemos que asegurarnos que estamos usando el repositorio stable del embedian, los otros no me funcionaron para eso nos fijamos en el archivo: /etc/apt/sources.list.d/emdebian.sources.list

Se deberia ver asi:

# The Emdebian toolchain repository
deb http://www.emdebian.org/debian/ stable main
deb-src http://www.emdebian.org/debian/ stable main

Luego ejecutamos:

#emsetup -a armel --verbose

Este comando se encarga de hacer todo el trabajo engorroso de setear el toolchain y dejárnoslo pronto.
En caso de que falle podríamos probar con:

#apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.3-arm-linux-gnueabi g++-4.3-arm-linux-gnueabi

Esto instala los paquetes esenciales para poder crosscompilar

Para probar todo hacemos:

echo '
#include <stdio.h>
int main(){
printf("hola");
return 0;
} ' > test.c

Por ultimo compilamos y lo probamos en alguna maquina arm:

$arm-linux-gnueabi-gcc -static test.c -o test.o

por Daedalus (Daedalus2027@gmail.com), el 25 de febrero de 2010 a las 02:10

Epsilon de la máquina

El Epsilon de la máquina es un numero que nos permite saber la precision de esta.
Es decir citando a wikipedia: "El épsilon es el número decimal más pequeño que, sumado a 1, la computadora nos arroja un valor diferente de 1, es decir, que no es redondeado."

Aqui dejo el codigo del programa en C que hice:

Archivo epsilon.c
/* Epsilon example */
#include <stdio.h>

int main(){
int steps;
steps=0;
float fepsilon=1.0;
while(fepsilon+1.0>1.0){
steps+=1;
fepsilon=fepsilon/2.0;
}
printf("Epsilon: %E , Steps: %i, presicion=float \n",fepsilon,steps);

steps=0;

double depsilon=1.0;
while(depsilon+1.0>1.0){
steps+=1;
depsilon=depsilon/2.0;
}
printf("Epsilon: %E , Steps: %i, presicion=double \n",depsilon,steps);

return 0;
}

Este codigo lo probe en 3 maquinas un Pentium 3 de 800MHZ 32 bit de precisión, en un PlayStation3 procesador CELL_BE de 64bit con registros de 128bit y en El Tmobile G1 con Android que tiene un procesador ARMv6.

En el Pentium 3:
daedalus@p3:~$ gcc epsilon.c -o epsilon.o
daedalus@p3:~$ ./epsilon.o
Epsilon: 5.421011E-20 , Steps: 64, presicion=float
Epsilon: 5.421011E-20 , Steps: 64, presicion=double

En el PlayStation3:
daedalus@ps3:~$ gcc epsilon.c -o epsilon.o
daedalus@ps3:~$ ./epsilon.o
Epsilon: 1.110223E-16 , Steps: 53, presicion=float
Epsilon: 1.110223E-16 , Steps: 53, presicion=double


daedalus@ps3:~$ spu-gcc epsilon.c -o epsilon_spu.o
daedalus@ps3:~$ ./epsilon_spu.o
Epsilon: 1.110223E-16 , Steps: 53, presicion=float
Epsilon: 1.110223E-16 , Steps: 53, presicion=double

Tanto la version CPU como SPU me dieron el mismo resultado.

En el Android(Tmobile G1):

Croscompile con:

$arm-linux-gnueabi-gcc --static epsilon.c -o epsilon_arm

Transfiero con:

 ./adb push epsilon_arm /data/local/bin/epsilon_arm

$/data/local/bin/epsilon_arm
Epsilon: 1.110223E-16 , Steps: 53, presicion=float 
Epsilon: 1.110223E-16 , Steps: 53, presicion=double


Otro ejemplo:

Archivo epsilon.py
def epsilon_calc():
  epsilon=1.0
  steps=0
  while(epsilon+1.0>1.0):
    epsilon=epsilon/2
    steps+=1
  print "epsilon=", epsilon, "steps=", steps
epsilon_calc()

Este mismo ejemplo en python en tres arquitecturas distintas  ya nombradas y arm-eabi(android) con ASE.

Me devuelven el mismo resultado:

$ python epsilon.py
epsilon= 1.11022302463e-16 steps= 53

Lo cual me hace suponer que la maquina virtual también se encarga de arreglar la presicion de los cálculos, es decir estos son mucho mas lentos que si se ejecutaran directamente en el hardware es decir se abstraen del hardware. Valga la redundancia es la idea de las virtual machines!

El valor 1.11022302463e-16 es un valor minimo estandar de la IEEE en precision de calculo.

Interesante no?

por Daedalus (Daedalus2027@gmail.com), el 25 de febrero de 2010 a las 01:48

24 de febrero de 2010

Marcos Crispino

Augmented Reality

La "realidad aumentada" (augmented reality en inglés) parece ser el tema del momento.

Básicamente, consiste en mostrar información obtenida de Internet sobre objetos reales: un edificio, un libro, etc.

Hoy vi una notica (en algún lado que ahora no me acuerdo) sobre un nuevo producto llamado Recognizr, que permite ver información asociada a una persona mediante una foto tomada con el teléfono móvil.



Otro producto que parece estar muy bueno es Google Goggles:



Creo que nadie puede dudar que en los próximos tiempos vamos a ver mucha innovación en esta área. Lo único que me precupa es que parece que todas las aplicaciones interesantes funcionan en Android...

por noreply@blogger.com (Marcos Crispino), el 24 de febrero de 2010 a las 23:34

Dario Clavijo

Vuelve Epica a Uruguay

Me comento mi amigo Andres Canavesi que la banda Epica la cual realiza una mezcla entre metal sinfónico power y gótico vuelve a Uruguay esta vez se presentaran en Montevideo mi ciudad natal.

















En la Sección Tour dates de la pagina oficial de Epica podemos ver la fecha agendada, la banda estará tocando el 20 de abril del 2010 en el Teatro de Verano.

Una fotito...




































Grrrrrr!!!

por Daedalus (Daedalus2027@gmail.com), el 24 de febrero de 2010 a las 03:35

23 de febrero de 2010

Marcos Crispino

Índice de los arrays

Ayer empecé a leer Dreaming in Code, que en una parte dice:
Maybe you noticed that I've called this Chapter 0. I did not mean to make an eccentric joke but, rather, to tip my hat to one small difference between computer programmers and the rest of us: Programmers count from zero, not from one. [...]
Why do programers count from zero? Because computers count from zero! And so programmers train themselves to count that way too, [...]
Si bien no es del todo cierto, yo soy un programador y cuento desde el uno, es verdad que las computadoras cuentan desde el cero...

Cualquiera que haya programado un loop sobre los elementos de un array en C, C++, Java, C#, o cualquier otro lenguaje que tenga sus raíces en C, sabe que los elementos van de 0 a lenght-1. Algo así:
for (int i = 0; i < array.length; i++) { ... }
Lo que nunca me había cuestionado, es por qué es así... Y después de pensarlo un poquito, la respuesta es bien simple: en C, los arrays son punteros a una dirección de memoria, que contiene el primer elemento. El índice es el desplazamiento con respecto al puntero. Así, para acceder al primer elemento del array, el desplazamiento a usar es cero, y por eso se accede con a[0]. Todos los lenguajes que vinieron atrás de C, aunque no manejen punteros directamente, mantienen la misma convención.

Toda una revelación :)

por noreply@blogger.com (Marcos Crispino), el 23 de febrero de 2010 a las 20:01