Un cuarto de siglo

Pasaron 25 años ya de aquel año que nos iba a encontrar “unidos o dominados”.

Quienes nos dedicamos a la tecnología educativa hemos perdido varias batallas últimamente.

Una de las batallas perdidas que más me duele y me cuesta comprender es la del sistema operativo Huayra. Hermoso, eficiente, adaptado a las necesidades educativas y localizado (es decir, vuelto local, argentinizado). Creo que la causa principal de este bajo nivel de adopción fue el doble booteo con el que venían las netbooks del plan Conectar Igualdad, que trajo como consecuencia el nulo uso de Huayra por parte de los equipos docentes.

Otra batalla perdida, también dolorosa y difícil de entender es el desinterés por la accesibilidad. Crear contenidos accesibles significa -por poner un ejemplo- cuidar el contraste de colores para que todas las personas puedan ver (¿es mayor el costo de un color que el otro en una pantalla? ¿o simplemente quienes diseñan contenido son insensibles o les falta capacitación?). Cumplir los estándares, nada más, nada menos. Se mejoraría la vida de todas las personas, todas, porque quienes no tenemos hoy una discapacidad, si tenemos suerte vamos a envejecer, y allí los dolores de mano, los problemas de vista, las dificultades para encontrar algo en una pantalla poco usable, van a hacernos sufrir los sitios mal diseñados.

Y la tercera es nueva, tan nueva que todavía no la entiendo. La batalla por los derechos de autor de aquellas cosas que subimos a la web, como este texto, con licencias libres, que hoy son usadas como alimento de la inteligencia artificial. En esta sí que nos mataron. Al final, nuestro sueño de una Internet libre, abierta, alimentada por cultura libre, está siendo pisoteado por empresas gigantes, por nubelistas dueños de los nuevos feudos informacionales, que se alimentan de nuestras producciones para recrear textos, imágenes, videos, ¡código!.

Así que en este cuarto de siglo de tantas batallas perdidas, también en lo político y cultural en mi país, Argentina, sólo queda el refugio de las redes humanas que fuimos construyendo. Nuestra salvación, creo yo, está en las personas con las que compartimos cada viaje: compañeros/as de estudio, de trabajo, la familia, las amistades. Y como los árboles en otoño, dejar que se caigan esas hojas para crear nuevas cuando llegue el momento.

Mis deseos para el próximo año: no seguir perdiendo batallas, profundizar amistades y redes presenciales, estudiar, aprender, compartir.

Licencias abiertas: una introducción a los derechos de autor en educación

Comparto la presentación de la charla sobre derechos de autor en educación brindada para las Jornadas de Acceso Abierto organizadas por el CRAI de la Universidad del Chubut. ¡Gracias por la invitación!

Accesibilidad web: para todas las personas, para tu propio futuro

Me invitaron a participar de las Jornadas Regionales de Software Libre que se realizaron este año en Santa Fe. Lamento no haber podido viajar pero sí pude enviar una participación a través de un video. Gracias al equipo organizador por la invitación.

Programando jueguitos con ChatGPT

Continuando con mis experimentos anteriores, estuve chateando hasta lograr programar un juego completo.

Este es el chat en el que le fui pidiendo a la herramienta que me generase un código, dándole poco a poco más detalles de cómo quería que funcione: Enlace al chat. (al final me quedé sin créditos para ChatGPT 4o y por eso no puedo seguir ahora)

En este enlace se puede probar el juego: Hacé grande a tu país

Y el código resultante después de todo el chat es el siguiente:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Juego del Auto</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            font-family: Arial, sans-serif;
        }
        #title {
            font-size: 36px;
            margin: 20px;
            color: #007BFF; /* Azul */
        }
        #gameContainer {
            position: relative;
            width: 90%;
            height: 80vh;
            background-color: lightblue;
            overflow: hidden;
            border: 2px solid black;
        }
        #score {
            font-size: 24px;
            margin: 10px;
        }
        #car {
            position: absolute;
            bottom: 10px;
            width: 100px;
            height: 50px;
            display: flex;
            flex-direction: column;
        }
        #car div {
            height: 33.33%;
        }
        #car .top, #car .bottom {
            background-color: #75AADB; /* Celeste */
        }
        #car .middle {
            background-color: white;
        }
        .word {
            position: absolute;
            font-size: 18px;
            color: black;
        }
        #message {
            font-size: 36px;
            color: #8A2BE2; /* Violeta azulado */
            margin: 20px;
            text-align: center;
        }
        #restartButton {
            display: none;
            padding: 10px 20px;
            font-size: 18px;
            cursor: pointer;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 5px;
            margin-top: 20px;
        }
        .centered {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            display: flex;
            flex-direction: column;
            align-items: center;
        }
    </style>
</head>
<body>
    <div id="title">Hacé que tu país sea un gran país</div>
    <div id="score">Puntaje: 0</div>
    <div id="gameContainer">
        <div id="car">
            <div class="top"></div>
            <div class="middle"></div>
            <div class="bottom"></div>
        </div>
    </div>
    <div id="message" class="centered"></div>
    <div class="centered">
        <button id="restartButton" onclick="restartGame()">Volver a jugar</button>
    </div>

    <script>
        const gameContainer = document.getElementById('gameContainer');
        const car = document.getElementById('car');
        const scoreDisplay = document.getElementById('score');
        const messageDisplay = document.getElementById('message');
        const restartButton = document.getElementById('restartButton');
        let score = 0;
        let carPosition = gameContainer.offsetWidth / 2 - car.offsetWidth / 2;
        const words = [
            "asfalto", "educación pública", "hospital público", "iluminación de la calle", "semáforos",
            "vacunas obligatorias", "regulación del uso de armas", "control de calidad en la comida",
            "netbooks para estudiantes de escuela pública", "universidades en todo el país", "boleto estudiantil",
            "satélites", "trenes estatales", "apoyo al cine nacional", "becas para deportistas",
            "Centro para deportistas de Alto Rendimiento", "clubes barriales", "orquestas juveniles",
            "Sistema operativo Huayra", "Rutas", "Plazas", "Juegos en las plazas", "créditos para viviendas",
            "pensión para discapacidad", "medicamentos gratis para personas jubiladas", "jubilaciones altas"
        ];
        let gameInterval;
        let carWidth = 100;
        let carHeight = 50;

        car.style.left = carPosition + 'px';
        car.style.width = carWidth + 'px';
        car.style.height = carHeight + 'px';

        document.addEventListener('keydown', (event) => {
            if (event.key === 'ArrowLeft') {
                carPosition = Math.max(0, carPosition - 10);
                car.style.left = carPosition + 'px';
            } else if (event.key === 'ArrowRight') {
                carPosition = Math.min(gameContainer.offsetWidth - car.offsetWidth, carPosition + 10);
                car.style.left = carPosition + 'px';
            }
        });

        function createWord() {
            const word = document.createElement('div');
            word.classList.add('word');
            word.textContent = words[Math.floor(Math.random() * words.length)];
            word.style.left = Math.random() * (gameContainer.offsetWidth - 100) + 'px';
            word.style.top = '0px';
            gameContainer.appendChild(word);

            function fall() {
                const wordTop = parseFloat(word.style.top);
                if (wordTop + word.offsetHeight >= gameContainer.offsetHeight - car.offsetHeight) {
                    const wordLeft = parseFloat(word.style.left);
                    const carLeft = parseFloat(car.style.left);
                    if (wordLeft < carLeft + car.offsetWidth && wordLeft + word.offsetWidth > carLeft) {
                        score++;
                        scoreDisplay.textContent = `Puntaje: ${score}`;
                        gameContainer.removeChild(word);
                        checkGameStatus();
                        adjustCarSize(1.10);
                    } else if (wordTop + word.offsetHeight >= gameContainer.offsetHeight) {
                        score--;
                        scoreDisplay.textContent = `Puntaje: ${score}`;
                        gameContainer.removeChild(word);
                        checkGameStatus();
                        adjustCarSize(0.90);
                    } else {
                        word.style.top = wordTop + 2 + 'px';
                        requestAnimationFrame(fall);
                    }
                } else {
                    word.style.top = wordTop + 2 + 'px';
                    requestAnimationFrame(fall);
                }
            }
            fall();
        }

        function adjustCarSize(factor) {
            carWidth *= factor;
            carHeight *= factor;
            car.style.width = carWidth + 'px';
            car.style.height = carHeight + 'px';
        }

        function checkGameStatus() {
            if (score < 0) {
                endGame('Perdiste');
            } else if (score >= 20) {
                endGame('Ganamos. Hiciste que Argentina sea un país más grande.');
            }
        }

        function endGame(message) {
            clearInterval(gameInterval);
            messageDisplay.textContent = message;
            messageDisplay.style.display = 'block';
            restartButton.style.display = 'block';
        }

        function restartGame() {
            score = 0;
            scoreDisplay.textContent = 'Puntaje: 0';
            messageDisplay.textContent = '';
            messageDisplay.style.display = 'none';
            restartButton.style.display = 'none';
            const wordsOnScreen = document.querySelectorAll('.word');
            wordsOnScreen.forEach(word => gameContainer.removeChild(word));
            carWidth = 100;
            carHeight = 50;
            car.style.width = carWidth + 'px';
            car.style.height = carHeight + 'px';
            gameInterval = setInterval(createWord, 2000);
        }

        gameInterval = setInterval(createWord, 2000);
    </script>
</body>
</html>

ChatGPT para crear código

En estos días estuve haciendo pequeños experimentos para crear archivos SVG, sitios web o interactivos con javascript, usando ChatGPT.

Los resultados son sorprendentes (y emocionantes!)

Comparto aquí tres videos y varios prompts.

Algunos prompts

Crear gráfico de torta interactivo

Quiero que crees un interactivo en donde pueda modificar tres variables a través de tres sliders. Esos tres sliders deben tener valores desde 0 hasta 100. A un costado debe hacerse un gráfico de torta que represente los valores de cada uno de los sliders. El gráfico de torta debe ocupar un 50% de la pantalla. Necesito que el código esté en javascript y lo incluyas en un archivo html. Los colores del gráfico tienen que ser: azul, rojo y amarillo.

Crear gráfico de barras interactivo

Por favor, crea el código en javascript insertado en un archivo HTML que realice un gráfico de barras con tres datos. Los datos son números del 1 al 100. Para cada uno hay un campo de texto con los títulos: Enero, Febrero, Marzo. Debajo se muestra un promedio de los tres valores con el título: Promedio trimestral. El gráfico debe ocupar un 50% de la pantalla.

Crear gráfico lineal interactivo

Crea el código en javascript insertado en un archivo HTML. En pantalla se ve un gráfico lineal donde se muestren los puntos resultantes de las siguientes variables: A, B y C. Para brindar el valor de cada variable tiene que haber un slider que permita ir desde 0 hasta 100. El gráfico debe unir los tres puntos a través de segmentos. El gráfico tiene que ocupar el 50% de la pantalla.

Generar imágenes de tipo SVG

Hola, por favor, ¿podés hacerme el código SVG de una flor con cinco pétalos color rosado?

Crear un sitio web accesible

Por favor, creá el HTML y el CSS por separado, para una página que tenga un menú horizontal en la parte de arriba. Las opciones del menú son: Inicio, productos, contacto.

Los cuatro principios de la accesibilidad

Las pautas del consorcio de la triple W (W3C) se agrupan en cuatro principios:

  • Perceptible: utilizar subtitulado para quien no puede oir, textos alternativos para quien no puede ver la imagen
  • Operable: todo el contenido debe poder utilizarse desde un teclado y desde los dispositivos de apoyo
  • Comprensible: utilizar lenguaje simple y ayudas claras
  • Robusto: seguir los estándares para que todo el contenido sea compatible con cualquier dispositivo

Estos principios guían la elaboración de contenidos sin barreras, para que todas las personas puedan utilizar la web independientemente de tener una discapacidad, conexión lenta, dispositivo antiguo o una limitación temporal, permanente o situacional.

En este interactivo creado con H5P repasamos cuáles de las pautas corresponden a cada principio:

Fuente de la información: https://accesibilidadweb.dlsi.ua.es/?menu=principios-2.1

Terminal de GNU/Linux – Machete de comandos útiles

En esta entrada voy a ir guardando los comandos que siempre busco y los enlaces de donde los saqué.

  • Buscar contenido dentro de un grupo de archivos de texto: grep “textoquese busca” /home/ *.php
    Más información: https://fortinux.gitbooks.io/humble_tips/content/usando_la_linea_de_comandos/tutorial_usar_grep_para_buscar_texto_dentro_de_archivos_en_gnulinux.html
  • Listar solamente los directorios en la carpeta actual: find . -maxdepth 1 -type d

Más información: joseblanco.pro – varias formas de listar solo directorios en linux

  • Convertir videos con FFMPEG: ffmpeg -i video.mkv nuevovideo.avi

Más información: linuxadictos – aprende a convertir videos desde la terminal

  • Saber mi dirección ip: ifconfig
  • Conocer mi dirección ip pública: curl ifconfig.me

Más información: ionos – dirección ip en linux

Resguardo de recursos educativos en línea

El contenido de este posteo fue elaborado en forma colaborativa junto con Lila Pagola, Matías Bordone, Flisol Córdoba y Ate Filo de UNC

Los enlaces a veces dejan de estar disponibles, especialmente en contextos de cambio.

¿Qué se puede hacer para resguardar el material?

Una forma de prevenir los enlaces rotos en caso de que un recurso deje de estar disponible es realizar una copia de seguridad en tu computadora. Esto permitiría que pudieras acceder en adelante, desde tu equipo, cuando lo necesites.

Sin embargo, hay una manera de realizar copias de resguardo que sean accesibles desde cualquier equipo y para todas las personas, siempre que se trate de recursos cuya licencia te permita crear una copia. El recurso tiene que decir explícitamente que tiene licencia Creative Commons, GPL, o alguna otra licencia abierta (ver Cultura libre).

Archive.org: Biblioteca sin fines de lucro

WayBackMachine (“la máquina del tiempo de internet”) pertenece a Archive.org, que es una biblioteca sin fines de lucro que busca conformar una biblioteca digital de millones re recursos con licencia abierta.

¿Cómo resguardar un recurso?