domingo, 10 de mayo de 2026

Dos IAs, un juego DOS: DeepSeek planeó, Nemotron programó… y salió muy básico (pero jugable)

 

 El experimento: revivir el Paratrooper de los 90 sin escribir una línea de código


 

    Hace unos días quise jugar al mítico Paratrooper de los DOS, ese donde controlas un cañón antiaéreo y derribas paracaidistas enemigos. Pero no quise descargar un emulador ni programarlo yo mismo. Quería ver si dos inteligencias artificiales podían hacerlo por mí, cada una con un rol diferente.

    El resultado fue un juego funcional, sí, pero muy básico. Nada de físicas avanzadas, ni sonido, ni helicópteros. Pero el cañón dispara, los enemigos caen, las vidas disminuyen y se puede perder. Vamos, lo justo para sentir nostalgia durante cinco minutos.

¿Cómo lo hice? Te cuento el proceso, las herramientas y las lecciones aprendidas.

 

Las dos IAs y sus roles

IARolLo que hizo
DeepSeek (yo, el asistente)Arquitecto / PlanificadorDiseñó la estructura del proyecto (archivos TS, CSS, HTML), escribió los prompts detallados que luego se enviarían a la otra IA.
Nemotron 3 Super FreeCodificadorRecibió los prompts de DeepSeek y generó el código fuente del juego (TypeScript, CSS y HTML).

Importante: No usé OpenCode con el modelo Nemotron. Simplemente copié los prompts que DeepSeek me dió y los pegué en la interfaz de Nemotron 3 Super Free (un modelo gratuito que promete entender código heredado y lenguajes retro, disponible en varias plataformas de IA).

 

Paso 1: DeepSeek planifica la estructura

    Le pedí a DeepSeek que me ayudara a crear un Paratrooper en TypeScript, con CSS e HTML, pero con una condición: el código debía ser generado por otra IA. Así que DeepSeek no escribió el juego, sino que generó una serie de prompts listos para copiar y pegar.

Estos prompts incluían:

  • Un tsconfig.json para compilar TypeScript.

  • Un index.html con canvas, marcador de vidas y botón de reinicio.

  • Un styles.css con aspecto retro.

  • Un game.ts completo con la lógica: cañón que sigue al ratón, disparo con clic, paracaidistas que caen, colisiones, vidas, game over y reinicio.

DeepSeek también me advirtió que el resultado probablemente sería muy básico si no iteraba mucho. Y tenía razón.

 

Nemotron 3 Super Free escribe el código

Copié el prompt más grande (el de game.ts) y se lo pegué a Nemotron 3 Super Free. En menos de un minuto, la IA devolvió un código completo. Luego hice lo mismo con los prompts de los otros archivos.

Al abrir index.html en el navegador… ¡funcionó a la primera! El cañón se movía con el ratón, los paracaidistas caían desde arriba, los disparos los eliminaban y las vidas se reducían al tocar el suelo.

Pero también noté limitaciones evidentes:

  • Colisiones imprecisas: A veces la bala pasaba cerca del enemigo y lo eliminaba igual.

  • Sin cadencia de disparo: Podía lanzar balas como ametralladora.

  • Sin animaciones: Los paracaidistas eran rectángulos marrones con un cuadro blanco encima (el paracaídas). Nada de sprites.

  • Sin helicópteros: Solo paracaidistas básicos.

  • El reinicio a veces dejaba balas "fantasma" en el array.

En resumen: cumple la mecánica principal, pero sin ningún detalle de refinamiento. Es un prototipo funcional, no un juego pulido.

 

¿Se puede mejorar con más prompts?

Por supuesto. Le pedí a DeepSeek que generara prompts de corrección: limitar disparos, ajustar colisiones, limpiar el array al reiniciar. Copié esos nuevos prompts a Nemotron, y tras dos o tres iteraciones el juego mejoró notablemente.

Pero incluso después de varias rondas, el resultado seguía siendo "muy básico" comparado con el Paratrooper original de DOS. La razón es que Nemotron 3 Super Free parece estar optimizado para código sencillo y directo, no para simulaciones complejas o juegos con estado delicado.

Comparativa: lo que prometí vs. lo que obtuve

CaracterísticaEstado final
Cañón sigue al ratón✅ Sí
Disparo con clic✅ Sí
Paracaidistas caen✅ Sí
Colisiones bala-enemigo✅ Sí, pero algo imprecisas
Vidas (3) y game over✅ Sí
Botón de reinicio✅ Sí, aunque a veces con bugs
Límite de disparos❌ No inicialmente, sí tras corrección
Sonido❌ No
Explosiones❌ No
Helicópteros❌ No
Puntuaciones altas❌ No

En una palabra: básico.

Lecciones aprendidas para quien quiera repetirlo

  1. Las IAs no reemplazan el criterio humano – Sin mis correcciones (los prompts adicionales de DeepSeek), el juego habría sido casi injugable.

  2. Nemotron 3 Super Free es buenísimo para prototipos rápidos, pero no esperes un juego comercial.

  3. DeepSeek (o cualquier asistente conversacional) es ideal para diseñar la arquitectura y los prompts, porque entiende el contexto global del proyecto.

  4. La iteración es clave – Con cada prompt de corrección, el juego mejora un poco. Tres o cuatro iteraciones ya dan un resultado decente.

  5. El resultado "muy básico" no es malo – A veces solo queremos revivir un recuerdo, no crear el próximo indie hit. Y para eso, estas herramientas son perfectas.

    Reflexión final: ¿mereció la pena?

    Absolutamente sí. En menos de una hora, sin escribir una sola línea de código manual, tuve un juego jugable en el navegador. Mi sobrino de 10 años lo probó y se divirtió disparando a los paracaidistas. Claro, después de cinco minutos dijo "está muy fácil" y se fue a jugar Roblox. Pero para mí, ver ese cañón moviéndose torpemente fue como viajar a 1992.

    Si tú también quieres revivir un clásico DOS sin complicarte, te recomiendo este método: usa una IA para planificar (DeepSeek, ChatGPT, Claude) y otra para codificar (Nemotron, Copilot, Codeium). El resultado será básico, pero funcional. Y la gracia está en el proceso.

    Bonus: el código final (muy básico) que generó Nemotron

    Por si quieres probarlo o mejorarlo, te dejo el enlace a mi repositorio https://github.com/davdomin/paratrooper. No es bonito, pero funciona.

     

     

 

 

 

 

 

 

domingo, 3 de mayo de 2026

El cambio de dAcli7 desde Access a SQL Server

Caso real de optimización en dAcli: de Access a SQL Server

Migración desde Access a SQL Server
Migración desde Access a SQL Server

Durante años convivimos con un problema que muchos sistemas legacy conocen demasiado bien: la base de datos funcionaba… hasta que dejaba de funcionar.

Y cuando dejaba de funcionar, no era un bug menor. Era algo peor: corrupción de datos.

El contexto real: software en condiciones no ideales

dAcli es un sistema de gestión utilizado en laboratorios clínicos en Venezuela, un entorno donde existe una variable crítica que muchas arquitecturas no contemplan: los cortes eléctricos.

Durante años, el sistema utilizó Microsoft Access como motor de base de datos, lo que terminó siendo un punto débil en este contexto.

El problema: Access y apagones

Cada vez que ocurría un corte eléctrico, existía una probabilidad real de que la base de datos:

  • Quedara corrupta.
  • No pudiera abrirse.
  • Obligara a restaurar respaldos.

Esto no era un evento aislado. Era recurrente.

La única defensa posible era aumentar la frecuencia de respaldos, lo que generaba otros problemas operativos:

  • Pérdida de datos recientes.
  • Interrupciones en el laboratorio.
  • Reinicios periódicos de la base de datos.

Incluso con pocos usuarios concurrentes (5 o 6), los problemas de concurrencia eran constantes.

El parche: manejar concurrencia desde el código

Para mitigar estos problemas, se implementaron soluciones a nivel de código:

  • Bloqueos manuales.
  • Validaciones adicionales.
  • Control de acceso a datos.

Estas soluciones redujeron conflictos, pero introdujeron un nuevo problema: lentitud generalizada del sistema. Con el tiempo, el código comenzó a crecer de forma desordenada.

20 años de código acumulado

El sistema acumuló una gran cantidad de código innecesario:

  • Funciones no utilizadas.
  • Formularios huérfanos.
  • Lógica duplicada.
  • Loops innecesarios.
  • Implementaciones antiguas mal diseñadas.

Era imposible mejorar el rendimiento sin enfrentar este problema directamente.

El proceso: limpieza manual y refactorización

Se realizó un proceso completo de limpieza de código, de forma manual:

  • Eliminación de código muerto.
  • Simplificación de lógica.
  • Reestructuración de módulos.

Este proceso duró aproximadamente seis meses, trabajando en horarios nocturnos y fines de semana.

Durante este tiempo, múltiples funcionalidades dejaron de funcionar temporalmente. Fue un proceso iterativo de ruptura y reconstrucción.

La decisión clave: migrar a SQL Server

Paralelamente, se decidió migrar el sistema a Microsoft SQL Server.

La migración no fue automática. Se realizó de forma manual, aprovechando para mejorar la estructura de datos.

Cambios realizados

  • Normalización de la base de datos.
  • Cambio de tipos de datos.
  • Creación de índices.
  • Reescritura de consultas.
  • Centralización del acceso a datos en una sola capa.

Se creó una clase que concentra todas las consultas, permitiendo desacoplar el sistema del motor de base de datos.

Function generarCodigo(tabla As String, CampoClave As String)
    Dim rs As New ADODB.Recordset
    rs.Open "SELECT MAX([" & CampoClave & "]) FROM [" & tabla & "]", conexion
    If Not IsNumeric(rs(0)) Then
        generarCodigo = 1
    Else
        generarCodigo = rs(0) + 1
    End If
End Function

Public Function DSQL(ByVal consultaSQL As String) As ADODB.Recordset
    Dim rs As New ADODB.Recordset
    On Error GoTo errorHandler
    rs.Open consultaSQL, MPrincipal.base, adOpenStatic, adLockOptimistic, adCmdText
    Set DSQL = rs
    Exit Function

errorHandler:
    Dim ErrorDescripcion
    ErrorDescripcion = Err.Description & vbCrLf & "#" & Err.number & " source:" & Err.Source
    MPrincipal.Log "sql", "Error:" & ErrorDescripcion & vbCrLf & consultaSQL
    If MPrincipal.RunningInVB Then
        Debug.Print consultaSQL
        MsgBox ErrorDescripcion & vbCrLf & consultaSQL, vbCritical
        Debug.Assert True
    End If
    MsgBox "No puedo completar la operacion"
End Function

Public Function Execute(ByVal consultaSQL As String, Optional silence As Boolean = False) As Boolean
    On Error GoTo errorHandler
    MPrincipal.base.Execute consultaSQL
    Execute = True
    Exit Function

errorHandler:
    Debug.Print Err.Description & vbCrLf & consultaSQL
    MPrincipal.Log "sql", Err.Description & vbCrLf & consultaSQL
    If Not silence Then
        MsgBox "Accion no realizada", vbCritical
    End If
    Execute = False
End Function

Function EscaparComillas(ByVal consultaSQL As String) As String
    EscaparComillas = consultaSQL
    Exit Function
    Dim partesConsulta() As String
    Dim i As Integer
    
    partesConsulta = Split(consultaSQL, " ")
    
    For i = LBound(partesConsulta) To UBound(partesConsulta)
        If partesConsulta(i) Like "*'*" Then
            partesConsulta(i) = Replace(partesConsulta(i), "'", "''")
        End If
    Next i
    
    EscaparComillas = Join(partesConsulta, " ")
End Function

Con la nueva arquitectura, se aplicaron mejoras clave:

  • Uso de stored procedures.
  • Implementación de caché.
  • Reducción de consultas redundantes.
  • Optimización de consultas pesadas.
  • Reducción del tráfico de red.

El sistema dejó de depender de lógica distribuida en el cliente y pasó a aprovechar mejor el motor de base de datos.

Resultados

Antes

  • Lentitud constante.
  • Bloqueos frecuentes.
  • Corrupción de bases de datos.
  • Reinicios periódicos.

Después

  • Fluidez general del sistema.
  • Consultas rápidas.
  • Estabilidad operativa.
  • Eliminación práctica de corrupción por apagones.

El cambio fue significativo tanto a nivel técnico como operativo.

Impacto en clientes

Actualmente:

  • Más del 90% de los laboratorios han migrado.
  • El sistema supera los 200 clientes.
  • Los clientes que inicialmente dudaban por costos terminaron adoptando la nueva arquitectura.

La diferencia en estabilidad y rendimiento justificó completamente el cambio.

Lecciones aprendidas

  • Los problemas de rendimiento muchas veces son problemas de arquitectura.
  • Los parches técnicos generan deuda acumulativa.
  • La limpieza de código es esencial en sistemas de larga vida.
  • Los motores de base de datos tienen límites claros según el contexto.
  • La estabilidad es una característica crítica en entornos reales.

Conclusión

Este proceso no fue simplemente una optimización. Fue una evolución completa del sistema.

dAcli pasó de ser un sistema funcional a convertirse en una plataforma estable y confiable para la operación diaria de laboratorios clínicos.

En entornos donde la continuidad operativa es crítica, este tipo de decisiones técnicas marcan la diferencia.

Página web de dAcli: www.dacli.com

sábado, 2 de mayo de 2026

Hice un Coliseo de IAs en Python para ver quién juega mejor ajedrez

 


¿Qué sucede cuando enfrentas dos lógicas de programación distintas en un entorno de reglas estrictas? Para responder esto, desarrollé un proyecto en Python que funciona como un entorno de ejecución (Engine) donde diferentes scripts de IA pueden competir entre sí.

En este post, explico cómo diseñé el tablero, las reglas y el experimento de enfrentar a white.py contra black.py

1. El Árbitro: Un motor de reglas puras

A diferencia de otros proyectos, aquí el "motor" no es quien juega. Su única misión es ser el sistema operativo del tablero. Está programado para:

  • Validar movimientos legales: Asegurar que ninguna IA intente saltarse las reglas.

  • Gestionar el estado: Controlar enroques, capturas al paso y promociones.

  • Detectar el final: Aplicar las reglas de tablas por insuficiencia de material, triple repetición y la regla de los 50 movimientos.

2. El Experimento: white.py vs. black.py

La verdadera magia ocurre en los archivos externos. El motor actúa como un "Coliseo" que le entrega el estado actual del tablero a cada archivo y espera una respuesta.

Esto permite realizar experimentos de Benchmarking de IA:

  • Lógica de Búsqueda: ¿Quién calcula mejor, un script basado en Minimax o uno basado en heurísticas experimentales?

  • Optimización: Cómo afecta el tiempo de respuesta (time.time()) en la calidad de la jugada devuelta.

  • Heurísticas de Evaluación: Comparar cómo diferentes algoritmos valoran la posición de las piezas en el tablero.

3. Anatomía del Motor (The Backbone)

El código está diseñado para ser modular y transparente. Algunos puntos clave de la implementación:

  • Clonación de Tablero: El motor permite a las IAs clonar el estado actual para simular jugadas futuras sin afectar la partida real.

  • PGN Builder: Generación automática de notación estándar para que las partidas puedan ser analizadas en visores externos.

  • Visualización en Consola: Un sistema de renderizado ASCII que permite seguir la "pelea" en tiempo real desde la terminal.

4. ¿Por qué separar el tablero de la lógica?

Separar el motor de los jugadores (white.py y black.py) ofrece ventajas críticas para el desarrollo de software:

  1. Modularidad: Puedes cambiar la lógica de una IA sin tocar una sola línea de código de las reglas del ajedrez.

  2. Imparcialidad: Ambos scripts reciben exactamente la misma información del estado del juego (get_state()).

  3. Escalabilidad: Es fácil añadir nuevos "jugadores" y enfrentarlos en un torneo tipo Round Robin.


El experimento: Crónica de una masacre algorítmica

El desarrollo de este coliseo no fue lineal; fue una evolución de "supervivencia del más apto". En las primeras pruebas, GPT, utilizando un prompt inicial optimizado, barrió completamente con las versiones básicas de Gemini y superó con claridad a DeepSeek. Parecía que el trono estaba definido.

Sin embargo, el panorama cambió cuando entró Claude en escena. Con una lógica de cálculo mucho más profunda y una gestión del árbol de decisiones superior, Claude destronó a GPT y "destrozó" a todos los demás competidores sin piedad.

Lo más interesante del experimento vino después: al aplicar los principios de optimización y la estructura de código que usaba Claude a las otras IAs, lograron una nivelación. Aunque seguían jugando con menos precisión, estas versiones mejoradas pudieron empezar a forzar tablas por repetición. Pasaron de suicidios tácticos a partidas donde la defensa era lo suficientemente sólida para no perder.


Del código al tablero: ¿Cómo se genera el PGN?

Para que estas partidas no se queden solo en líneas de log en la terminal, el software implementa un PGN Builder. El PGN (Portable Game Notation) es el estándar universal para registrar partidas de ajedrez.

¿Cómo funciona el flujo de datos?

  1. Captura del movimiento: Cada vez que white.py o black.py deciden una jugada, el motor registra la casilla de origen, la de destino y si hubo captura o promoción.

  2. Traducción a Notación Algebraica: El motor convierte las coordenadas internas del array (ej. [7, 4]) a notación estándar (ej. e1).

  3. Detección de estados especiales: El software verifica si el movimiento resultó en jaque (+), jaque mate (#) o si fue un enroque (O-O).

  4. Exportación: Al finalizar el juego, todos estos strings se concatenan siguiendo el formato: 1. e4 e5 2. Nf3 Nc6....

Visualización en Chess.com o Lichess

El resultado final es un bloque de texto que puedes copiar y pegar directamente en herramientas como el Analizador de Chess.com o Chess Compass. Estas plataformas leen el archivo PGN, reconstruyen la partida visualmente y te permiten usar motores como Stockfish para ver exactamente en qué jugada Claude le ganó la partida a Gemini.

 

 

Desafío Open Source

He subido este entorno de competencia a mi repositorio. Si eres desarrollador y quieres probar tu propia lógica de ajedrez, solo tienes que crear tu propio script y enfrentarlo en el tablero.

 Repositorio del proyecto: https://github.com/davdomin/chess_motor

¿Qué estrategia usarías para ganar: un ataque agresivo basado en material o una defensa sólida basada en posición? Te leo en los comentarios.

 

viernes, 1 de mayo de 2026

Keep Code Left (KCL): El arte de escribir código limpio y lineal


 

En el 2015, mientras trabajaba en Software Andina, tuve el privilegio de asistir a una sesión que cambió por completo mi forma de ver un archivo de código fuente. En aquel entonces, recibíamos frecuentemente a desarrolladores de Estados Unidos que venían a compartir su experiencia.

Uno de esos visitantes fue Mick Andrew, Director de Desarrollo en Sage. Mick, amigo cercano de mi jefe de entonces, John Rutherfurd, nos trajo una presentación titulada: "Keep Code Left" (Mantén el código a la izquierda).

El título parecía simple, pero la filosofía detrás era profunda. Como desarrolladores, solemos enfocarnos en que el código funcione, olvidando que el código se lee muchas más veces de las que se escribe. Mick nos enseñó que, con unas pocas reglas de "libro de cocina", podíamos transformar una lógica enredada y profundamente anidada en algo limpio, lineal y extraordinariamente fácil de mantener.

¿Qué es Keep Code Left?

En esencia, Keep Code Left (KCL) es un estilo de programación diseñado para maximizar la legibilidad. El nombre se refiere a la estructura visual: cuanta más sangría (identación) tiene tu lógica, más se empuja el código hacia la derecha, y más difícil le resulta al cerebro humano rastrear el "estado" y el flujo del programa.

Los objetivos de KCL son claros:

  • Simplificar la lógica: Crear un flujo lineal en lugar de ramificado.

  • Mejorar la legibilidad: Permitir que cualquier desarrollador entienda el objetivo de un método de un solo vistazo.

  • Reducir errores de mantenimiento: El código simple es más difícil de romper.

  • Agilizar las revisiones de código: Proporciona un estándar visual que se verifica rápidamente.

Desde aquel día en 2015, he aplicado estos principios en casi todos mis proyectos. Hoy quiero compartir contigo cómo aplicarlo y por qué tu "yo del futuro" te lo agradecerá.

El Problema de la Anidación

Cuando el código se anida profundamente, surgen problemas inmediatos:

  • Es difícil de leer línea por línea.

  • La lógica principal queda "enterrada" en el centro del archivo.

  • Aumenta la carga cognitiva (tienes que recordar qué condición abrió cada llave).

El Principio Maestro

Evita la anidación innecesaria. Prefiere salidas tempranas (early returns) y un flujo lineal.

En lugar de envolver la lógica principal en múltiples bloques if, manejamos los casos de error o excepciones primero y salimos de la función inmediatamente.

Ejemplo 1: Código Anidado (Incómodo)

public void ProcessOrder(Order order)
{
    if (order != null)
    {
        if (order.IsValid())
        {
            if (order.Items.Count > 0)
            {
                // La lógica principal está aquí, escondida
                Save(order);
            }
        }
    }
} 

Ejemplo 1: Aplicando Keep Code Left (Mejor) 

 

public void ProcessOrder(Order order)
{
    if (order == null) return;
    if (!order.IsValid()) return;
    if (order.Items.Count == 0) return;

    // La lógica principal está "a la izquierda" y es visible
    Save(order);
}

Técnicas Clave de KCL

  1. Salidas Tempranas (Early Returns): Si no se cumplen las condiciones necesarias para continuar, sal de la función de inmediato.

  2. Cláusulas de Guarda (Guard Clauses): Protege tu lógica principal de datos nulos o inválidos al inicio del método.

  3. Reducción de Identación: Cada nivel de if o loop añade complejidad. Intenta mantener tu código con el menor número de "escalones" hacia la derecha posible.

  4. Enfócate en el "Happy Path": El camino feliz (donde todo sale bien) debe ser el eje central y más visible del método.

    Beneficios en el Mundo Real

    Aplicar KCL no es solo un capricho estético; tiene impactos reales en el equipo:

  5. Revisiones de código más veloces: Los patrones son fáciles de detectar sin necesidad de conocer todo el contexto del negocio.

  6. Menos bugs: Al reducir la complejidad visual, los errores lógicos saltan a la vista.

  7. Onboarding rápido: Un desarrollador nuevo puede entender qué hace una función en segundos.

Un consejo para trabajar con IA

Hoy en día, cuando usamos herramientas como  Claude o Copilot, notarás que a menudo generan código muy anidado por defecto. Es extremadamente útil pedirles explícitamente: "Escribe este código siguiendo los principios de Keep Code Left" o "Usa cláusulas de guarda para evitar la anidación". Esto te ahorrará mucho tiempo de refactorización posterior.

viernes, 10 de noviembre de 2023

Cómo Crear una Extensión de Google Chrome para Abrir WhatsApp Web con un Solo Clic



 ¿Te gustaría tener la capacidad de abrir WhatsApp Web con un solo clic desde tu navegador? ¡Buenas noticias! Puedes lograrlo fácilmente creando tu propia extensión personalizada para Google Chrome. En esta guía paso a paso, te mostraré cómo hacerlo. Puedes visitar nuestro articulo sobre como crear una extension en chrome

Paso 1: Configuración Inicial

Antes de comenzar, asegúrate de tener un directorio para tu proyecto. En este ejemplo, llamaremos al directorio "WhatsAppWebLauncher".

Paso 2: Archivo manifest.json

Crea un archivo llamado manifest.json en tu directorio y agrega el siguiente contenido:

{
    "name": "WhatsApp Web Launcher",
    "description": "Open WhatsApp Web for a given phone number.",
    "version": "0.1.0",
    "manifest_version": 3,
    "icons": {
        "16": "/images/icon16.png",
        "32": "/images/icon32.png",
        "48": "/images/icon48.png",
        "128": "/images/icon128.png"
    },
    "action": {
        "default_popup": "popup.html",
        "default_icon": {
            "16": "/images/icon16.png",
            "32": "/images/icon32.png",
            "48": "/images/icon48.png",
            "128": "/images/icon128.png"
        }
    },
    "permissions": [
        "storage",
        "activeTab",
        "scripting",
        "tabs"
    ],
    "content_security_policy": {
        "extension_pages": "script-src 'self'; object-src 'self';"
    }
}

Asegúrate de reemplazar "WhatsApp Web Launcher" con el nombre que desees para tu extensión.

Paso 3: Archivo popup.html

Crea un archivo llamado popup.html y agrega el siguiente contenido:

<!DOCTYPE html>
<html>
<head>
  <title>WhatsApp Web Launcher</title>
</head>
<body>
  <h3>Phone number:</h3>
  <input type="text" id="phoneNumber" placeholder="Ej. +51-1234567" value="">
  <button id="openButton">Open in WhatsApp Web</button>
  <script src="popup.js"></script>
</body>
</html>

Paso 4: Archivo popup.js

Crea un archivo llamado popup.js y agrega el siguiente contenido:

document.addEventListener('DOMContentLoaded', function () {
  var phoneNumberInput = document.getElementById('phoneNumber');

  phoneNumberInput.focus();
  document.getElementById('openButton').addEventListener('click', function() {
    openWhatsApp();
  });
  function openWhatsApp() {
    var phoneNumber = phoneNumberInput.value;
    if (phoneNumber) {
      phoneNumber = phoneNumber.replace(/[^\d]/g, '');
      var whatsappWebUrl = 'https://web.whatsapp.com/send?phone=' + phoneNumber;
      chrome.tabs.create({ url: whatsappWebUrl });
    } else {
      alert('Por favor, ingresa un número de teléfono.');
    }
  }
});

Paso 5: Cargar la Extensión

  1. Abre Google Chrome y ve a chrome://extensions/.
  2. Habilita "Modo de desarrollador" en la esquina superior derecha.
  3. Haz clic en "Cargar descomprimida" y selecciona la carpeta de tu proyecto.

¡Listo! Ahora deberías ver el ícono de tu extensión en la barra de herramientas de Chrome.

Beneficios de Crear Extensiones Personalizadas

Crear tus propias extensiones de navegador personalizadas no solo es divertido, sino que también puede mejorar tu productividad. Puedes adaptar tu navegador exactamente a tus necesidades y automatizar tareas comunes.

Contribuye y Mejora

Este proyecto está en GitHub. Si encuentras problemas o tienes sugerencias de mejora, ¡contribuye al desarrollo! https://github.com/davdomin/chrome_whatsapp

¡Espero que encuentres útil esta extensión personalizada! ¡Háganos saber si tienes alguna pregunta o sugerencia!


jueves, 9 de noviembre de 2023

Descubre las Novedades en Quasar v2.13.1: Más Potencia, Menos Errores

 ¡La espera ha terminado! Quasar Framework acaba de lanzar su versión v2.13.1, cargada de emocionantes características y correcciones que mejorarán significativamente tu experiencia de desarrollo. A continuación, exploraremos algunas de las principales actualizaciones que esta versión trae consigo:



Características Destacadas:

1. Atributo "tag" para QField

  • Ahora, en QField, puedes aprovechar el nuevo atributo "tag" para personalizar aún más la renderización del componente. ¡Más flexibilidad para adaptarse a tus necesidades específicas!

2. Mejoras en el Manejo de Errores

  • Correcciones de errores importantes, como el uso incorrecto de etiquetas <label> en QField, que garantizan un rendimiento más suave y consistente.

Soluciones a Problemas Heredados:

1. Problemas de Herencia de v1 Abordados

  • Se han abordado problemas heredados de la versión 1, como el informe de errores en la consola de desarrollo, asegurando una transición sin problemas a la última versión.

Cómo Actualizar:

Si ya eres un usuario de Quasar, actualizar a la última versión es sencillo. Solo sigue estos pasos:

    1. Instalación de la Nueva Versión:

      npm install -g quasar@2.13.1

    2. Actualización de Proyectos Existentes:

      quasar upgrade

    ¡Y eso es todo! Tu proyecto estará listo para aprovechar al máximo las nuevas funcionalidades y correcciones.

    Comunidad y Colaboración:

    Quasar Framework es posible gracias a la increíble comunidad de desarrolladores. Si encuentras problemas o tienes sugerencias, ¡no dudes en contribuir y ser parte de la evolución de Quasar!

    Este lanzamiento marca otro paso hacia adelante en la misión de Quasar de proporcionar un marco de trabajo poderoso y flexible para el desarrollo web. ¡Esperamos que disfrutes de todas las nuevas mejoras!

    Para obtener más detalles sobre esta versión, consulta aquí.

    ¡Feliz codificación con Quasar v2.13.1! 🚀✨

Dos IAs, un juego DOS: DeepSeek planeó, Nemotron programó… y salió muy básico (pero jugable)

   El experimento: revivir el Paratrooper de los 90 sin escribir una línea de código        Hace unos días quise jugar al mítico Paratrooper...